Как переименовать все папки и файлы в нижний регистр в Linux? - PullRequest
155 голосов
/ 30 сентября 2008

Я должен рекурсивно переименовать полное дерево папок, чтобы нигде не было заглавных букв (это исходный код C ++, но это не должно иметь значения). Бонусные баллы за игнорирование CVS и SVN контрольных файлов / папок. Предпочтительным способом будет сценарий оболочки, поскольку оболочка должна быть доступна на любом компьютере с Linux.

Были некоторые допустимые аргументы о деталях переименования файла.

  1. Я думаю, что файлы с одинаковыми строчными именами должны быть перезаписаны, это проблема пользователя. При проверке в файловой системе без учета регистра первая тоже будет перезаписана второй.

  2. Я бы рассмотрел символы A-Z и преобразовал их в a-z, все остальное просто вызывает проблемы (по крайней мере, с исходным кодом).

  3. Сценарий необходим для запуска сборки в системе Linux, поэтому я думаю, что изменения в файлах управления CVS или SVN должны быть опущены. В конце концов, это просто проверка заказа. Может быть, «экспорт» более уместен.

Ответы [ 27 ]

0 голосов
/ 28 февраля 2015

Slugify Rename (regex)

Не совсем то, о чем просил ОП, но то, что я надеялся найти на этой странице:

Версия "slugify" для переименования файлов, чтобы они были похожи на URL-адреса
(то есть включают только буквенно-цифровые, точки и тире):

rename "s/[^a-zA-Z0-9\.]+/-/g" filename
0 голосов
/ 14 февраля 2019
find . -depth -name '*[A-Z]*'|sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'|sh

Я не пробовал более сложные сценарии, упомянутые здесь, но ни одна из версий для командной строки не работала для меня на моем Synology NAS. rename недоступен, и многие из вариантов find терпят неудачу, потому что кажется, что он придерживается более старого имени уже переименованного пути (например, если он находит ./FOO с последующим ./FOO/BAR, переименовывая ./FOO до ./foo будет по-прежнему перечислять ./FOO/BAR, даже если этот путь больше не действителен). Выше команда работала для меня без каких-либо проблем.

Ниже приводится объяснение каждой части команды:


find . -depth -name '*[A-Z]*'

При этом будет найден любой файл из текущего каталога (измените . на любой каталог, который вы хотите обработать), используя поиск в глубину (например, он выведет список ./foo/bar перед ./foo), но только для файлов, которые содержат заглавные буквы. Фильтр -name применяется только к базовому имени файла, а не к полному пути. Так что это будет список ./FOO/BAR, но не ./FOO/bar. Это нормально, так как мы не хотим переименовывать ./FOO/bar. Мы хотим переименовать ./FOO, но это будет упомянуто позже (вот почему -depth важно).

Эта команда сама по себе особенно полезна для поиска файлов, которые вы хотите переименовать. Используйте это после полной команды переименования для поиска файлов, которые все еще не были заменены из-за конфликтов имен файлов или ошибок.


sed -n 's/\(.*\/\)\(.*\)/mv -n -v -T \1\2 \1\L\2/p'

Эта часть читает файлы, выведенные find, и форматирует их в команде mv с использованием регулярного выражения. Опция -n останавливает sed от печати ввода, а команда p в регулярном выражении поиска и замены выводит замененный текст.

Само регулярное выражение состоит из двух захватов: части до последнего / (которая является каталогом файла) и самого имени файла. Каталог остается без изменений, но имя файла преобразуется в нижний регистр. Таким образом, если find выведет ./FOO/BAR, оно станет mv -n -v -T ./FOO/BAR ./FOO/bar. Опция -n mv гарантирует, что существующие строчные файлы не будут перезаписаны. Опция -v заставляет mv выводить каждое внесенное изменение (или не вносить - если ./FOO/bar уже существует, выводится что-то вроде ./FOO/BAR -> ./FOO/BAR, отмечая, что никаких изменений не было сделано). -T очень важен здесь - он рассматривает целевой файл как каталог. Это гарантирует, что ./FOO/BAR не будет перемещен в ./FOO/bar, если этот каталог существует.

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


sh

Это довольно очевидно. Он направляет все сгенерированные команды mv в интерпретатор оболочки. Вы можете заменить его на bash или любую другую оболочку по своему вкусу.

0 голосов
/ 25 декабря 2018

Это хорошо работает и в macOS:

ruby -e "Dir['*'].each { |p| File.rename(p, p.downcase) }"
0 голосов
/ 30 сентября 2008
( find YOURDIR -type d | sort -r;
  find yourdir -type f ) |
grep -v /CVS | grep -v /SVN |
while read f; do mv -v $f `echo $f | tr '[A-Z]' '[a-z]'`; done

Сначала переименуйте каталоги снизу вверх sort -r (где -depth недоступен), затем файлы. Тогда grep -v / CVS вместо find ...- prune , потому что это проще. Для больших каталогов для f в ... может переполнить некоторые буферы оболочки. Используйте найти ... | в то время как читать , чтобы избежать этого.

И да, это приведет к блокированию файлов, которые отличаются только регистром ...

0 голосов
/ 29 сентября 2017

Никто не предлагает набирать текст?

typeset -l new        # always lowercase
find $topPoint |      # not using xargs to make this more readable
  while read old
  do mv "$old" "$new" # quotes for those annoying embedded spaces
  done

На эмуляциях Windows, таких как git bash, это может не сработать, поскольку окна не чувствительны к регистру. Для них добавьте шаг, в котором файл mv находится сначала под другим именем, например, «$ old.tmp», а затем в $ new.

0 голосов
/ 23 июня 2017

Если вы используете Arch Linux , вы можете установить rename пакет из AUR, который предоставляет команду renamexm как /usr/bin/renamexm исполняемый вместе с ней руководство .

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

Преобразовать в нижний регистр

rename -l Developers.mp3 # or --lowcase

Преобразовать в верхний регистр

rename -u developers.mp3 # or --upcase, long option

Другие опции

-R --recursive # directory and its children

-t --test # dry run, output but don't rename

-o --owner # change file owner as well to user specified

-v --verbose # output what file is renamed and its new name

-s/str/str2 # substite string on pattern

--yes # Confirm all actions
0 голосов
/ 15 января 2015

Мне нужно было сделать это на установке cygwin в Windows 7 и обнаружил, что я получил синтаксические ошибки с предложениями из вышеупомянутого, которые я попробовал (хотя, возможно, пропустил рабочий вариант), однако это решение прямо из ubutu форумы работают из банки: -)

ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done

(примечание: ранее я заменял пробел на подчеркивание, используя

for f in *\ *; do mv "$f" "${f// /_}"; done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...