Как я могу использовать переименовать, чтобы рекурсивно переименовать все в верхний регистр


11

Я хотел бы рекурсивно переименовать все файлы и папки (подпапки) в верхний регистр.

Я нашел несколько сценариев, которые будут делать это в нижнем регистре, но я не знаю, как их изменить, чтобы он делал это наоборот (снизу вверх).

Сценарий, который я нашел и работает для строчных букв, но я не знал, как его изменить:

rename 'y/A-Z/a-z/' *

Это из man rename.


Не зная ничего о команде переименования, я подозреваю, что если вы попытаетесь, rename 'y/a-z/A-Z/' *вы получите то, что вы хотите. Тщательно, когда вы проверяете это до конца.
Уорик

это не слишком (потому что первоначальный не был ...), но это работает. Я не могу понять, почему я не учился на этом обмане :), тогда!
jnhghy - Александру Jantea

Я думаю, что учитывая качество ответа Жиля, было бы хорошо, если бы вы приняли его ответ вместо моего. Он гораздо более полный, чем мой, и объясняет ваши варианты (и как все это работает). Спасибо.
Уорик

Ответы:


8

Обратите внимание, что вы используете скрипт Perl, называемыйrename распространяемым Debian и производными (Ubuntu, Mint,…). Другие дистрибутивы Linux поставляют совершенно другую и значительно менее полезную команду rename.

y/A-Z/a-z/переводит каждый символ в диапазоне Aчерез Zв соответствующий символ в диапазоне aчерез z, т.е. ASCII прописных букв в соответствующей строчной буквы. Для выполнения обратного перевода используйте y/a-z/A-Z/. Другой способ написать ту же команду , которая rename '$_ = uc($_)' *ucэто у PPER с функцией азы, а renameкоманда переименовывает файлы , основанная на преобразовании из к $_переменному.

rename '…' *переименовывает только файлы в текущем каталоге, потому что это то, что *соответствует. Точечные файлы (файлы, с которых начинается название .) тоже пропускаются.

Если вы хотите рекурсивно переименовывать файлы в текущем каталоге и в подкаталогах, вы можете использовать findкоманду для рекурсивного обхода текущего каталога. Здесь возникает трудность: если вы позвоните rename, это переименует и каталог, и часть базового имени. Если вы renameобращаетесь к каталогу, прежде чем возвращаться в него ( find -exec rename … {} \;), он findзапутывается, потому что он нашел каталог, но этот каталог больше не существует, когда он пытается спуститься в него. Вы можете обойти это, попросив findпройти по каталогу, прежде чем действовать, но затем вы попытаетесь переименовать foo/barего, FOO/BARно каталог FOOне существует.

Простой способ избежать этой трудности - заставить команду переименования действовать только на часть базового имени пути. Регулярное выражение ([^/]*\Z)соответствует последней части пути, которая не содержит /.

find . -depth -exec rename 's!([^/]*\Z)!uc($1)!e' {} +

Оболочка zsh предоставляет более удобные функции для переименования - даже более загадочно, чем Perl, но более краткая и часто более простая для составления.

Функция zmvпереименовывает файлы на основе шаблонов. Запустите autoload -U zmvодин раз, чтобы активировать его (поместите эту строку в свой .zshrc).

В первом аргументе zmv(шаблон для замены) вы можете использовать мощные шаблоны шаблонов zsh . Во втором аргументе zmv(текст замены) вы можете использовать функции расширения его параметров , включая модификаторы истории .

zmv -w '**/*' '$1$2:u'

Объяснение:

  • -w - автоматическое присвоение числовых переменных каждому шаблону подстановки
  • **/*- все файлы в подкаталогах, рекурсивно ( **/соответствует 0, 1 или более уровням подкаталогов)
  • $1 - первая числовая переменная, здесь совпадающая с частью каталога каждого пути
  • $2:u- вторая числовая переменная, здесь совпадающая с частью базового имени каждого пути, с :uмодификатором для преобразования значения в верхний регистр

В качестве дополнительного бонуса это учитывает настройки окружающего языка.

Если вы не уверены в zmvнаписанной вами команде, вы можете передать -nопцию, чтобы напечатать, что будет делать команда, и ничего не менять. Проверьте вывод и, если он делает то, что вы хотите, повторно запустите команду без -nфактического действия.


5

Украденный (с незначительным редактированием) из поста Жиля здесь

find <DIR> -depth -type d -exec rename -n 's!/([^/]*/?)$!\U/$1!' {} +


Это не действует рекурсивно.
Жиль "ТАК - перестань быть злым"

Правда. Я должен был прочитать вопрос правильно. У меня нет доступа к команде переименования, но я считаю, что это будет работать рекурсивно -find <dir> -exec rename 'y/a-z/A-Z/' {} \;
Уорик

Это немного сложнее, потому что вы переименовываете каталоги, в то время findкак возвращаетесь в них.
Жиль "ТАК - перестань быть злым"

@ Жиль - ОК. После небольшого исследования мне кажется, что мне нужно добавить опцию -depth, чтобы имена каталогов обрабатывались последними. Поэтому find <dir> -depth -exec rename 'y/a-z/A-Z/' {} \;следует решить вопрос с переименованием каталогов. Правильный?
Уорик

Нет, это все еще не работает, потому что renameизменения , например , foo/barк FOO/BARи FOOне существует в этой точке.
Жиль "ТАК - перестань быть злым"

2

Я хотел бы направить любого, кто все еще связан с этим ответом, к превосходному ответу, который Гилес Квернот дал на этот вопрос, который не требует find.

В результате команда будет:

shopt -s globstar
rename -n 'y/a-z/A-Z/' **

Но перед запуском, пожалуйста, прочитайте ответ, связанный с предостережениями относительно старых версий bash.

Наконец, в случае, если кому-то интересно, что делает y///команда perl regex. Вот ссылка на соответствующую документацию .


1

find -execdir| переименование

Это был бы лучший способ сделать это, если бы не безумие относительного пути, так как Perl regex fu не действует только на базовое имя:

PATH="$(echo "$PATH" | sed -E 's/(^|:)[^\/][^:]*//g')" \
  find a -depth -execdir rename 's/(.*)/\U$1/' '{}' \;

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

К сожалению, я не могу избавиться от этой PATHхакерской части, find -execdirотказывается что-либо делать, если у вас есть относительный путь в PATH...: /ubuntu/621132/why-using-the-execdir-action- является нестабильным-для-каталог-который-является-в-пути / 1109378 # 1109378


0

Попробуйте это после перемещения в каталог, где вы хотите переименовать файлы:

for word in `ls -ltr |tail -n +2 |awk '{print $9}'`
do
  a=$(echo $word | tr '[a-z]' '[A-Z]')
  mv $word $a
  echo "Done Successfully"
done

Не анализируйте выходные данные ls (и почему бы вам просто запустить ls -lобрезку столбцов, отличных от имени?) И используйте двойные кавычки вокруг подстановок переменных . Ваш код слишком сложен и разбит на имена файлов, содержащие пробелы и другие специальные символы. Используйте findили, **/чтобы перейти в подкаталоги, выходные данные lsпредназначены только для потребления человеком.
Жиль "ТАК - перестань быть злым"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.