Краткая версия с помощью "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"
).
Ранее отправленный будет работать отлично из поля или с несколькими корректировками к простым случаям, но существуют некоторые ситуации, которые Вы могли бы хотеть принять во внимание прежде, чем работать, пакет переименуйте:
, Что должно произойти, если у Вас есть два или больше имени на том же уровне в иерархии пути, которые отличаются только случаем, такой как ABCdef
, abcDEF
и aBcDeF
? Должен переименовать сценарий прерываться или просто предупреждать и продолжаться?
, Как Вы определяете нижний регистр для не имена US-ASCII? Если такие имена могли бы присутствовать, нужно проверить и исключить передачу, выполняются сначала?
при выполнении переименовать операции на CVS или SVN рабочие копии Вы могли бы повредить рабочую копию при изменении случая на именах файла или каталога. Сценарий должен также найти и скорректировать внутренние административные файлы, такие как .svn/entries или CVS/записи?
( 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 в... может переполнить некоторых буферов оболочки. Используйте , находят... |, в то время как считано избегать этого.
И да, это ударит файлы, которые отличаются только в случае, если...
Вот мое субоптимальное решение, с помощью Сценария оболочки удара:
#!/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" оба возвращает список папок в применимом порядке на переименование, я предпочел использовать "-глубина" для поиска папок.
for f in `find`; do mv -v "$f" "`echo $f | tr '[A-Z]' '[a-z]'`"; done
Это - маленький сценарий оболочки, который делает то, что Вы запросили:
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
Отметьте - действие глубины в первой находке.
Используя фиксатор имени файла 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
конечно, сценарий выше),
Исходный вопрос попросил игнорирование каталогов 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
Большинство ответов выше опасно, потому что они не имеют дело с именами, содержащими нечетные символы. Ваша самая безопасная ставка для такого рода вещи должна использовать 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
... хорошо угадайте что...