Я хочу в нижнем регистре имя каждого каталога в каталоге. С помощью каких команд я могу это сделать?
источник
Я хочу в нижнем регистре имя каждого каталога в каталоге. С помощью каких команд я могу это сделать?
Все каталоги на одном уровне или рекурсивно?
На одном уровне:
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
и т. Д., Есть последовательные заключенные в скобки группы в шаблоне. **
означает все (под) * каталоги, рекурсивно. Финал (/)
- это не группа в скобках, а квалификатор glob, означающий совпадение только с каталогами. ${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
гарантирует, что глубоко вложенные каталоги обрабатываются перед их предками. Обработка имени зависит от наличия /
; если вы хотите вызывать операцию в текущем каталоге, используйте ./*
(адаптация сценария оболочки, чтобы справиться .
или *
оставлена как упражнение для читателя).
Здесь я использую сценарий переименования Perl, который поставляется вместе с Debian и Ubuntu /usr/bin/prename
(как правило, также доступен rename
). На одном уровне:
rename 's!/([^/]*/?)$!\L/$1!' root/*/
Рекурсивно, с bash ≥4 или zsh:
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
Рекурсивно, переносимо:
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
mv -i a a
укажите «mv: переименуйте a в / a: неверный аргумент».-execdir
что удивительно: unix.stackexchange.com/questions/5412/… Затем я обнаружил, что в нем есть какое-тоPATH
безумие и он грустит :-(Нет ни одной команды, которая это сделает, но вы можете сделать что-то вроде этого:
Если вам нужно, чтобы он был надежным, вы должны учитывать, когда уже есть две директории, которые отличаются только регистром.
Как однострочник:
источник
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d
, но не смог понятьfor fd in */;
таким, чтобы избежать необходимости проверки, если это был каталог, но я понятия не имею, был ли этот инстинкт хорошим.tr
уже ожидает диапазон, такtr '[A-Z]' '[a-z]'
переводится[
с[
и]
в]
мимоходом. Это бесполезно, но безвредно; однако без кавычек оболочка расширит скобки, если в текущем каталоге будет файл с именем, состоящим из одной заглавной буквы.Я воспринял это как однострочную задачу :) Сначала создайте контрольный пример:
Я использую
find
для обозначения каталогов заглавными буквами, а затем с помощью нижнего регистра . Думаю, использование немного хакерство, но моя голова всегда взрывается, когда я пытаюсь избежать чего-то напрямую.sh -c 'mv {}
echo {} | tr [:upper:] [:lower:]
'sh -c
find
Имейте в виду: это решение не проверяет, приводит ли уменьшение размеров к столкновениям!
источник
mv -i
. Большая проблема в том, что вы не использовали правильные кавычки, поэтому ваша команда не будет выполнена, если в имени есть специальные символы (пробел или\[*?
). Там нет смысла использовать,find
если только повторения, а затем вам нужноfind -depth
, и-path
должно быть-name
. Смотрите мой ответ для рабочих примеров.mv -i
после написания этого. Хороший вопрос с цитатой ...find -execdir
| переименованиеЭто был бы лучший способ сделать это, если бы не безумие относительного пути, так как Perl regex fu не действует только на базовое имя:
-execdir
сначалаcd
в каталог, прежде чем выполнять только по базовому имени.К сожалению, я не могу избавиться от этой
PATH
хакерской части,find -execdir
отказывается что-либо делать, если у вас есть относительный путь вPATH
...: /ubuntu/621132/why-using-the-execdir-action- является нестабильным-для-каталог-который-является-в-пути / 1109378 # 1109378источник