Как я переименовываю все папки и файлы к нижнему регистру на Linux?

Я должен переименовать полное дерево папки рекурсивно так, чтобы никакая прописная буква не появлялась нигде (это - исходный код C++, но это не должно иметь значения).

Бонусные очки для игнорирования CVS и файлов/папок управления версиями Подверсии. Предпочтительным путем был бы сценарий оболочки, так как оболочка должна быть доступной на любом поле Linux.

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

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

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

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

163
задан Peter Mortensen 13 September 2019 в 11:16
поделиться

9 ответов

Краткая версия с помощью "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. S.

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

166
ответ дан Peter Mortensen 23 November 2019 в 21:14
поделиться

Ранее отправленный будет работать отлично из поля или с несколькими корректировками к простым случаям, но существуют некоторые ситуации, которые Вы могли бы хотеть принять во внимание прежде, чем работать, пакет переименуйте:

  1. , Что должно произойти, если у Вас есть два или больше имени на том же уровне в иерархии пути, которые отличаются только случаем, такой как ABCdef, abcDEF и aBcDeF? Должен переименовать сценарий прерываться или просто предупреждать и продолжаться?

  2. , Как Вы определяете нижний регистр для не имена US-ASCII? Если такие имена могли бы присутствовать, нужно проверить и исключить передачу, выполняются сначала?

  3. при выполнении переименовать операции на CVS или SVN рабочие копии Вы могли бы повредить рабочую копию при изменении случая на именах файла или каталога. Сценарий должен также найти и скорректировать внутренние административные файлы, такие как .svn/entries или CVS/записи?

2
ответ дан Mihai Limbășan 1 August 2019 в 05:19
поделиться
( 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

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

И да, это ударит файлы, которые отличаются только в случае, если...

0
ответ дан pklausner 23 November 2019 в 21:14
поделиться

Вот мое субоптимальное решение, с помощью Сценария оболочки удара:

#!/bin/bash
# first, rename all folders
for f in `find . -depth ! -name CVS -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming folder $f"
      mv -f "$f" "$g"
   fi
done

# now, rename all files
for f in `find . ! -type d`; do
   g=`dirname "$f"`/`basename "$f" | tr '[A-Z]' '[a-z]'`
   if [ "xxx$f" != "xxx$g" ]; then
      echo "Renaming file $f"
      mv -f "$f" "$g"
   fi
done

Редактирование: Я сделал некоторые модификации на основе предложений до сих пор. Теперь папки все переименованы правильно, mv не задает вопросы, когда полномочия не соответствуют, и папки CVS не переименованы (файлы управления CVS в той папке все еще переименованы, к сожалению).

Редактирование: С тех пор "находят - глубина" и "находит |, вид-r" оба возвращает список папок в применимом порядке на переименование, я предпочел использовать "-глубина" для поиска папок.

4
ответ дан Peter Mortensen 23 November 2019 в 21:14
поделиться
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
84
ответ дан rubo77 23 November 2019 в 21:14
поделиться

Это - маленький сценарий оболочки, который делает то, что Вы запросили:

root_directory="${1?-please specify parent directory}"
do_it () {
    awk '{ lc= tolower($0); if (lc != $0) print "mv \""  $0 "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it

Отметьте - действие глубины в первой находке.

3
ответ дан tzot 23 November 2019 в 21:14
поделиться

Используя фиксатор имени файла Larry Wall:

$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/'

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

4
ответ дан Peter Mortensen 23 November 2019 в 21:14
поделиться

Исходный вопрос попросил игнорирование каталогов SVN и CVS, которые могут быть сделаны путем добавления - чернослив к команде находки. Например, проигнорировать 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
ответ дан Ian Dickinson 23 November 2019 в 21:14
поделиться

Большинство ответов выше опасно, потому что они не имеют дело с именами, содержащими нечетные символы. Ваша самая безопасная ставка для такого рода вещи должна использовать 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"'

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

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

... хорошо угадайте что...

14
ответ дан Peter Mortensen 23 November 2019 в 21:14
поделиться
Другие вопросы по тегам:

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