Печатая строчными литерами все каталоги в соответствии с каталогом

Возможно, излишество, но я просто нашел это valgrind назвали хороший инструмент massif. Я протестировал его на xterm:

valgrind --trace-children=yes --tool=massif xterm
ms_print massif.out.* | less

И Вы получаете хороший график использования памяти:

    MB
4.230^                     #                    :::::::  :::      @@:     ::: 
     |   @                 #:::@::@@:::::@::::::: :: : ::: :::::::@ ::::::: ::
     |   @               ::#:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::::@@:::::::::: #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
   0 +----------------------------------------------------------------------->Mi
     0                                                                   292.4

наряду с чрезмерно подробной информацией об использовании памяти. Детали в valgrind руководстве.

Программы будут работать о 20x медленнее все же. Кроме того, я выполнил некоторые команды в xterm. Их объем потребляемой памяти был принят во внимание потому что --trace-children=yes опция там!

12
05.01.2011, 04:34
4 ответа

Все каталоги на одном уровне, или рекурсивно?

Zsh

На одном уровне:

autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'

Рекурсивно:

zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'

Объяснения: zmv переименовывает файлы, соответствующие шаблону согласно данному тексту замены. -o-i передачи -i опция каждому mv команда под капотом (см. ниже). В тексте замены, $1, $2, и т.д., последовательные заключенные в скобки группы в шаблоне. ** средства весь (sub) *directories, рекурсивно. Финал (/) не заключенная в скобки группа, а спецификатор шарика, означающий соответствовать только каталогам. ${2:l} преобразовывает $2 к нижнему регистру.

Портативный

На одном уровне:

for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done

Финал / ограничивает соответствие каталогами, и mv -i заставляет его попросить подтверждение в случае коллизии. Удалите -i перезаписывать в случае коллизии и использования yes n | for …. чтобы не быть запрошенным и не выполняют любое переименование, которое столкнулось бы.

Рекурсивно:

find root/* -depth -type d -exec sh -c '
    t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
    [ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;

Использование -depth гарантирует, что глубоко вложенные каталоги обрабатываются перед их предками. Обработка имени полагается на то, чтобы там быть a /; если Вы хотите звонить, работают в текущем каталоге, используют ./* (адаптация сценария оболочки для преодоления . или * оставлен как осуществление для читателя).

Perl переименовывает

Здесь я использую Perl, переименовывают сценарий, который Debian и Ubuntu поставляют как /usr/bin/prename (обычно доступный как rename также). На одном уровне:

rename 's!/([^/]*/?)$!\L/$1!' root/*/

Рекурсивно, с ударом ≥4 или zsh:

shopt -s globstar  # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/

Рекурсивно, портативно:

find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
10
27.01.2020, 19:55
  • 1
    По крайней мере, на OS X это перестанет работать, если какие-либо каталоги уже будут нижним регистром: mv -i a a дайте "mv: переименуйте к a/a: Недействительный аргумент". –  Janus 05.01.2011, 14:09
  • 2
    @Janus: Право, Вы получаете сообщение об ошибке, которое ужасно (хотя безопасный в командной строке). Но так или иначе я должен был использовать zmv, который заботится об этом случае. проверка –  Gilles 'SO- stop being evil' 05.01.2011, 21:05

Нет единственной команды, которая сделает это, но можно сделать что-то вроде этого:

for fd in */; do
  #get lower case version
  fd_lower=$(printf %s "$fd" | tr A-Z a-z)
  #if it wasn't already lowercase, move it.
  [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"
done

При необходимости в нем, чтобы быть устойчивыми, необходимо объяснить, когда уже существует два каталога, которые отличаются только в случае, если.

Как острота:

for fd in */; do fd_lower=$(printf %s "$fd" | tr A-Z a-z) && [ "$fd" != "$fd_lower" ] && mv "$fd" "$fd_lower"; done
4
27.01.2020, 19:55
  • 1
    Это обнаружилось на полпути посредством моей записи (в основном то же) предложение: for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done –  frabjous 05.01.2011, 06:02
  • 2
    я пытался разработать его с find -type d, но не мог вполне получить его –  Michael Mrozek♦ 05.01.2011, 06:07
  • 3
    Мой инстинкт должен был бы сделать for fd in */;, таким образом избегая потребности в проверке, если это был каталог, но я понятия не имею, был ли этот инстинкт хорошим. –  Steven D 05.01.2011, 06:27
  • 4
    Да, для...*/было бы лучше. –  Shawn J. Goff 05.01.2011, 06:42
  • 5
    @Shawn: tr уже ожидает диапазон, таким образом, tr '[A-Z]' '[a-z]' переводит [ кому: [ и ] кому: ] мимоходом. Это бесполезно, но безопасно; однако без кавычек оболочка развернула бы скобки, если бы был файл с именем с одной прописной буквой в текущем каталоге. –  Gilles 'SO- stop being evil' 05.01.2011, 10:21

Я взял это в качестве проблемы остроты :) Во-первых, установите тестовый сценарий:

$ for d in foo Bar eVe; do mkdir -p dcthis/$d; touch dcthis/a${d}.txt; done
$ ls dcthis/
Bar     aBar.txt    aeVe.txt    afoo.txt    eVe     foo

Я использую find определить каталоги с прописными буквами и затем downcase их через sh -c 'mv {} echo {} | tr [:upper:] [:lower:]'. Угадайте использование sh -c немного выхода взлома, но моя голова всегда взрывается, когда я пытаюсь выйти из вещей для find непосредственно.

$ (cd dcthis && find . -maxdepth 1 -type d -path '*[A-Z]*' -exec sh -c 'mv {} `echo {} | tr [:upper:] [:lower:]`' \;)
$ ls dcthis/
aBar.txt    aeVe.txt    afoo.txt    bar     eve     foo

Будьте осторожны: Это решение не проверяет, приводит ли downcasing к коллизиям!

0
27.01.2020, 19:55
  • 1
    коллизии легка: mv -i. Большая проблема состоит в том, что Вы не использовали надлежащее заключение в кавычки, таким образом, Ваша команда перестанет работать, если будут специальные символы (пробел или \[*?) где угодно на имя. Нет никакого смысла из использования find если, рекурсивно вызывая, и затем Вам не нужно find -depth, и -path должен быть -name. См. мой ответ для рабочих примеров. –  Gilles 'SO- stop being evil' 05.01.2011, 21:07
  • 2
    @Giles.Спасибо! Я видел Ваш mv -i после записи этого. Положительная сторона с заключением в кавычки... –  Janus 06.01.2011, 07:45

find -execdir rename

Это переименовывает файлы и каталоги с регулярным выражением, влияющим только на базовые имена.

Так что для префикса вы можете сделать:

PATH=/usr/bin find. -depth -execdir rename 's/(.*)/\L$1/' '{}' \;

или только для файлов:

PATH=/usr/bin find. -type f -execdir rename 's/(.*)/\L$1/' '{}' \;

-execdirсначала cds в каталог перед выполнением только для базового имени.

Я объяснил это более подробно в:https://stackoverflow.com/questions/16541582/find-multiple-files-and-rename-them-in-linux/54163971#54163971

0
27.01.2020, 19:55

Теги

Похожие вопросы