Назад | Перейти на главную страницу

Как я могу рекурсивно изменить регистр файлов и папок в bash

У меня есть несколько файлов и папок, все в верхнем регистре, которые я хочу переименовать в их эквивалент в нижнем регистре. Как лучше всего сделать это в bash в системе Linux?

В качестве примера у меня может быть:

.
|-- FOLDER0
|   |-- SUBFOLDERA
|   `-- SUBFOLDERB
`-- FOLDER1
    `-- AFILE.TXT

И я хочу преобразовать его в:

.
|-- folder0
|   |-- subfoldera
|   `-- subfolderb
`-- folder1
    `-- afile.txt

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

find . -depth -print0 | xargs -0 rename -n '$_ = lc $_'

Уберите флаг -n, если вы уверены, что он делает то, что вы хотите.

Это скорее комментарий и мета-наблюдение за тем, как работает этот форум, но я очень твердо уверен, что об этом следует говорить громче, чем если бы я просто оставил комментарий в ответе rudedog. Это также комментарий, адресованный скорее людям, у которых могут быть проблемы. аналогичный на вопрос Дэвида Дина, но не идентичный.

Рекурсивными операциями по переименованию файлов легко нанести огромный ущерб. Позвольте мне сказать это еще раз, потому что это очень важно. Вы можете очень, очень быстро уничтожить огромное количество данных с помощью рекурсивных операций переименования файлов. Вы можете быстро вывести систему из строя. Вы можете очень быстро удалить 99% своих данных. Такие действия надо делать очень тщательно и с большим количеством размышлений, резервного копирования и тестовых прогонов.

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

  1. Версия "переименования", которую я использую, - это та же версия, которую вы используете, и обе они имеют привычные мне функции безопасности. "rename" - это не какая-то стандартная, нормальная утилита в unix, насколько я знаю. Вроде какой-то умный скрипт, который есть в каком-то дистрибутиве.
  2. "переименовать", как описано, имеет некоторую функцию безопасности, предотвращающую перезапись файла.
  3. либо изменяемые файлы имеют однозначные результаты в сжатом регистре, либо это не имеет большого значения, если в результирующем подкаталоге есть файлы в верхнем регистре, потому что результаты в сжатом регистре имели коллизию, и механизм изменения имени ничего не делает, если целевое имя уже существует.

Мне совершенно комфортно делать ярлыки. Однако я пытаюсь понять, что что-то является ярлык и каковы ограничения такого ярлыка, чтобы я знал, когда мне нужно запустить всегда правильную программу или в 10 000 раз быстрее, но не работает в некоторых крайних случаях.

Короче говоря, приведенный выше сценарий с использованием переименования на 100% оправдан в 90% случаев. Решение на 100% правильное в 100% случаев на самом деле немного сложное и требует некоторого ума при столкновении с конфликтами пространства имен.

Но, как я уже сказал, будь очень осторожно с рекурсивными файловыми операциями, особенно если они изменяют только метаданные, такие как разрешения или имена файлов. Их быстро и сложно отменить без резервного копирования ...

Вот пример того, как написать команду «переименовать» в bash, ksh или какой-нибудь другой современной оболочке, имеющей «наборный». Назовем этот скрипт / tmp / squash

#!/usr/local/bin/pdksh
# use some shell that supports typeset such as ksh, pdksh, or bash
# call this script from "xargs -0" and feed it with "find -print0"

typeset -l targetname || { echo "This shell doesn't support typeset!" >&2 ; exit 1 ; }
for file
do
  count=""
  target="$file"
  targetpath="${target%/*}/"
  targetname="${target##*/}"
  if
    [[ "$file" == "$targetpath$targetname" ]]  || [[ "$file" == . ]]
  then
    :
  else
    while
      test -e "$targetpath/$targetname""$count"
    do
      count=$((${count:-0}+1))
    done
    echo "renaming $file to $targetpath$targetname$count" >&2
    mv -n  "$file" "$targetpath$targetname$count"
  fi
done

Теперь вы можете выполнить следующие две команды, и все ваши файлы будут сжаты и не будут перезаписаны.

find /path/to/files -type f -print0 | xargs -0 /tmp/squash
find /path/to/files -type d -depth -print0 | xargs -0 /tmp/squash

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

Я полагаюсь на других за ответом, но -type f и -type d в качестве аргументов для поиска вернут файлы и каталоги соответственно. Если вы хотите сначала изменить файлы, затем каталоги ... затем сначала измените файлы, а затем каталоги.