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

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

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

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

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

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

Ответы [ 27 ]

236 голосов
/ 17 ноября 2011

меньше, но мне все равно нравится

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

В нечувствительных к регистру файловых системах, таких как HFS + в OS X, вы захотите добавить флаг -f

rename -f 'y/A-Z/a-z/' *
160 голосов
/ 30 сентября 2008

Краткая версия с использованием команды "rename".

find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

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

Или более подробная версия без использования "rename".

for SRC in `find my_root_dir -depth`
do
    DST=`dirname "${SRC}"`/`basename "${SRC}" | tr '[A-Z]' '[a-z]'`
    if [ "${SRC}" != "${DST}" ]
    then
        [ ! -e "${DST}" ] && mv -T "${SRC}" "${DST}" || echo "${SRC} was not renamed"
    fi
done

P. С.

Последний обеспечивает большую гибкость с помощью команды перемещения (например, "svn mv").

82 голосов
/ 30 сентября 2008
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
66 голосов
/ 31 августа 2014

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

zip -r foo.zip foo/*
unzip -LL foo.zip
14 голосов
/ 30 сентября 2008

Большинство ответов выше опасны, потому что они не имеют дело с именами, содержащими нечетные символы. Ваша самая безопасная ставка для такого рода вещей - использовать опцию find -print0, которая завершит имена файлов ascii NUL вместо \ n. Здесь я представляю этот скрипт, который изменяет только файлы, а не имена каталогов, чтобы не перепутать find.

find .  -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "$0")/$(basename "$0"); 
d=$(dirname "$0")/$(basename "$0"|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'

Я протестировал его, и он работает с именами файлов, содержащими пробелы, всевозможные кавычки и т. Д. Это важно, потому что, если вы запускаете от имени root один из тех других скриптов в дереве, который включает файл, созданный:

touch \;\ echo\ hacker::0:0:hacker:\$\'\057\'root:\$\'\057\'bin\$\'\057\'bash

... ну угадай, что ...

12 голосов
/ 10 ноября 2015

Это работает, если у вас уже есть или настроена команда rename (например, через brew install в Mac):

rename --lower-case --force somedir/*
10 голосов
/ 18 февраля 2017

Человек, которого вы, ребята, любите усложнять ...

переименовать 'y / A-Z / a-z /' *

6 голосов
/ 01 апреля 2016

Это работает на CentOS / Redhat или других дистрибутивах без * Perl-скрипта rename:

for i in $( ls | grep [A-Z] ); do mv -i "$i" "`echo $i | tr 'A-Z' 'a-z'`"; done

Источник: https://linuxconfig.org/rename-all-files-from-uppercase-to-lowercase-characters

(в некоторых дистрибутивах команда rename по умолчанию исходит от util-linux, а это другой несовместимый инструмент)

4 голосов
/ 30 сентября 2008

Исходный вопрос, заданный для игнорирования каталогов SVN и CVS, что можно сделать, добавив -prune к команде find. Например, игнорировать CVS:

find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print

[править] Я попробовал это, и встраивание перевода в нижний регистр в находку не сработало по причинам, которые я на самом деле не понимаю. Итак, измените это на:

$> cat > tolower
#!/bin/bash
mv $1 `echo $1 | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower 
$> find . -name CVS -prune -o -exec tolower '{}'  \;

Ian

4 голосов
/ 30 сентября 2008

Использование фиксатора имени файла Ларри Уолла

$op = shift or die $help;
chomp(@ARGV = <STDIN>) unless @ARGV;
for (@ARGV) {
    $was = $_;
    eval $op;
    die $@ if $@;
    rename($was,$_) unless $was eq $_;
}

это так же просто, как

find | fix 'tr/A-Z/a-z/'

(где исправить, конечно, сценарий выше)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...