Рекурсивное переименование, исключая текущий каталог

Может быть, я упускаю из виду то, о чем вы просите, но я думаю

du -sh *

делает именно то, что вы хотите. Здесь важно *. С -sвы получаете сводку для каждого каталога в командной строке , так что без явного каталога (неявного.)вы просто получите сводку для всего, а не для каждого из каталоги под верхним -уровнем по отдельности.

0
10.02.2020, 09:34
1 ответ

С find, который поддерживает предикат -mindepth:

 find. -mindepth 2 -type f -name '*.bak' | rename 's/\.bak$/.old/'

Предикат -mindepthпозволяет определить минимальную глубину поиска, при которой могут быть найдены совпадения. Нулевая глубина — это сам корневой путь поиска (.), глубина 1 — это все, что находится непосредственно под корневым путем поиска (, например. ./somename), а глубина 2 — это все, что непосредственно ниже (, например../somename/other)и др.

Обратите внимание, что регистронезависимое соответствие, которое делает -iname, не требуется, так как ваш renameв любом случае не будет переименовывать файлы, которые имеют другие типы заглавных букв суффикса имени файла, поэтому вместо этого я изменил его на тест -name.. Я также исправил ваш вызов rename, чтобы файлы со строкой bakв другом месте имени, например rebak.bak, не переименовывались странным образом (, например. вr.old.bak).

Я также добавил -type f, чтобы findучитывал только обычные файлы, т. е. не каталоги и т. д.

Для более портативного решения:

find. -mindepth 2 -type f -name '*.bak' -exec sh -c '
    for pathname do
        mv "$pathname" "${pathname%.bak}.old"
    done' sh {} +

Это не зависит от утилиты rename.

find. -mindepth 2 -type f -name '*.bak' -exec rename 's/\.bak$/.old/' {} +

Это вызов renameнепосредственно из find.

Связанные:


С помощью bashвы можете полностью пропустить findи вместо этого выполнить

shopt -s globstar dotglob

rename 's/\.bak$/.old/'./*/**/*.bak

Шаблон подстановки **соответствует любому количеству промежуточных подкаталогов. Этот специальный шаблон активируется опцией оболочки globstar. Начальный ./*/гарантирует, что мы ищем только в подкаталогах текущего каталога, а не в самом текущем каталоге.

Параметр оболочки dotglobобеспечивает соответствие скрытых имен шаблону.

Вышеупомянутое, однако, не будет выбирать только обычные файлы (, как и ваша команда find). Для этого используйте цикл:

shopt -s globstar dotglob

for pathname in./*/**/*.bak; do
    [[ ! -f $pathname ]] && continue
    rename 's/\.bak$/.old/' "$pathname"
done

Это также приведет к переименованию символических ссылок в обычные файлы.

2
28.04.2021, 23:23

Теги

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