Как переименовать все папки и файлы в нижний регистр в Linux?
Я должен рекурсивно переименовать полное дерево папок, чтобы нигде не появлялась заглавная буква (это исходный код C++, но это не имеет значения). Бонусные баллы за игнорирование файлов/папок управления CVS и SVN. Предпочтительным способом будет сценарий оболочки, так как оболочка должна быть доступна в любой Linux-системе.
были некоторые допустимые аргументы о деталях переименования файла.
Я думаю, что файлы с одинаковыми именами в нижнем регистре должны быть перезаписаны, это проблема пользователя. При проверке на случай игнорирования файловой системы будет перезаписать первый с последним, тоже.
Я бы рассмотрел символы A-Z и преобразовал их в a-z, все остальное просто вызывает проблемы (по крайней мере, с исходным кодом).
скрипт потребуется для запуска сборки в системе Linux, поэтому я думаю, что изменения в файлах управления CVS или SVN следует опустить. В конце концов, это всего лишь царапина. Возможно "экспорт" более уместен.
24 ответов
краткая версия с использованием .
find my_root_dir -depth -exec rename 's/(.*)\/([^\/]*)/\/\L/' {} \;
это позволяет избежать проблем с каталогами, которые переименовываются перед файлами и пытаются переместить файлы в несуществующие каталоги (например,"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
П. С.
последняя позволяет более гибко с помощью команды переместить (электронная. г. "svn mv"
).
еще меньше мне нравится
rename 'y/A-Z/a-z/' *
в нечувствительных к регистру файловых системах, таких как HFS+ OS X, вы захотите добавить флаг-f
rename -f 'y/A-Z/a-z/' *
просто попробуйте следовать, если вам не нужно заботиться об эффективности.
zip -r foo.zip foo/*
unzip -LL foo.zip
большинство ответов выше опасны, потому что они не имеют дело с именами, содержащими нечетные символы. Ваша самая безопасная ставка для такого рода вещей-использовать опцию find-print0, которая завершит имена файлов с ascii NUL вместо \n. Здесь я представляю этот скрипт, который только изменяет файлы, а не имена каталогов, чтобы не путать find.
find . -type f -print0 | xargs -0n 1 bash -c \
's=$(dirname "")/$(basename "");
d=$(dirname "")/$(basename ""|tr "[A-Z]" "[a-z]"); mv -f "$s" "$d"'
я протестировал его, и он работает с именами файлов, содержащими пробелы,все виды кавычек и т. д. Это важно, потому что если вы запустите, как root, один из тех других скриптов в дереве, который включает файл, созданный:
touch \;\ echo\ hacker::0:0:hacker:$\'7\'root:$\'7\'bin$\'7\'bash
... знаешь что?..
это работает если у вас уже есть или создать переименовать команда (например, через brew install в Mac):
rename --lower-case --force somedir/*
использование имени файла фиксаж Ларри Уолла
$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, что можно сделать, добавив-prune в команду find. Например, игнорировать CVS:
find . -name CVS -prune -o -exec mv '{}' `echo {} | tr '[A-Z]' '[a-z]'` \; -print
[edit] я попробовал это, и внедрение перевода нижнего регистра внутри находки не сработало по причинам, которые я на самом деле не понимаю. Итак, измените это на:
$> cat > tolower
#!/bin/bash
mv `echo | tr '[:upper:]' '[:lower:]'`
^D
$> chmod u+x tolower
$> find . -name CVS -prune -o -exec tolower '{}' \;
Иэн
вот мое неоптимальное решение, используя скрипт оболочки bash:
#!/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
Edit: я внес некоторые изменения, основанные на предложениях до сих пор. Теперь все папки переименованы правильно, mv не задает вопросов, когда разрешения не совпадают, и папки CVS не переименованы (файлы управления CVS внутри этой папки все еще переименованы, к сожалению).
Edit: поскольку "find-depth" и "find | sort-r" оба возвращают список папок в удобном порядке для переименования, я предпочел использование "- depth " для поиска папок.
Это небольшой скрипт, который делает то, что вы просили:
root_directory="${1?-please specify parent directory}"
do_it () {
awk '{ lc= tolower(); if (lc != ) print "mv \"" "\" \"" lc "\"" }' | sh
}
# first the folders
find "$root_directory" -depth -type d | do_it
find "$root_directory" ! -type d | do_it
обратите внимание на действие-depth в первом поиске.
это работает на CentOS / Redhat или других дистрибутивах без rename
Perl-скрипт:
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, и это другой, несовместимый инструмент)
ранее опубликованный будет работать отлично из коробки или с несколькими корректировками для простых случаев, но есть некоторые ситуации, которые вы можете принять во внимание перед запуском переименования пакета:
что должно произойти, если у вас есть два или более имен на одном уровне в иерархии путей, которые отличаются только в зависимости от случая, например
ABCdef
,abcDEF
иaBcDeF
? Должен ли скрипт rename прерваться или просто предупредить и продолжить?как сделать определите нижний регистр для нас-ASCII названий? Если такие имена могут присутствовать, следует ли сначала проверить и исключить пропуск?
Если вы выполняете операцию переименования на рабочих копиях CVS или SVN, вы можете повредить рабочую копию при изменении имени файла или каталога. Должен ли скрипт также находить и настраивать внутренние административные файлы, такие как .svn / записи или CVS / записи?
С MacOS,
установить rename
пакет,
brew install rename
использовать
find . -iname "*.py" -type f | xargs -I% rename -c -f "%"
эта команда найти все файлы с
не портативный, только Zsh, но довольно лаконичный.
во-первых, убедитесь, что zmv
загружается.
autoload -U zmv
кроме того, убедитесь, что extendedglob
на:
setopt extendedglob
затем использовать:
zmv '(**/)(*)~CVS~**/CVS' '${(L)2}'
для рекурсивно строчных файлов и каталогов, где имя не CVS.
в OSX mv-f показывает ошибку "тот же файл", поэтому я переименовываю дважды.
for i in `find . -name "*" -type f |grep -e "[A-Z]"`; do j=`echo $i | tr '[A-Z]' '[a-z]' | sed s/\-1$//`; mv $i $i-1; mv $i-1 $j; done
Я бы потянулся к python в этой ситуации, чтобы избежать оптимистически предполагаемых путей без пробелов или косых черт. Я также обнаружил, что python2
имеет тенденцию устанавливаться в большем количестве мест, чем rename
.
#!/usr/bin/env python2
import sys, os
def rename_dir(directory):
print('DEBUG: rename('+directory+')')
# rename current directory if needed
os.rename(directory, directory.lower())
directory = directory.lower()
# rename children
for fn in os.listdir(directory):
path = os.path.join(directory, fn)
os.rename(path, path.lower())
path = path.lower()
# rename children within, if this child is a directory
if os.path.isdir(path):
rename_dir(path)
# run program, using the first argument passed to this python script as the name of the folder
rename_dir(sys.argv[1])
for f in `find -depth`; do mv ${f} ${f,,} ; done
find -depth
печатает каждый файл и каталог, причем содержимое каталога печатается перед самим каталогом. ${f,,}
строчные буквы имени файла.
( 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 вместо найти ...- чернослив!--3--> потому что это проще. Для больших каталогов для f in ... может переполнить некоторые буферы оболочки. Использовать найти ... | пока читаем чтобы избежать этого.
и да, это будет clobber файлы, которые отличаются только в случае...
Slugify переименовать (регулярное выражение)
не совсем то, что ОП попросил, но то, что я надеялся найти на этой странице:
версия "slugify" для переименования файлов, чтобы они были похожи на URLs
(т. е. включать только буквенно-цифровые, точки и тире):
rename "s/[^a-zA-Z0-9\.]+/-/g" filename
мне нужно было сделать это на установке cygwin в Windows 7 и обнаружил, что я получил синтаксические ошибки с предложениями сверху, которые я пробовал (хотя я, возможно, пропустил рабочий вариант), однако это решение прямо из форумы ubutu работал из банки :-)
ls | while read upName; do loName=`echo "${upName}" | tr '[:upper:]' '[:lower:]'`; mv "$upName" "$loName"; done
(nb я ранее заменял пробелы подчеркиванием с помощью
for f in *\ *; do mv "$f" "${f// /_}"; done
если вы используете Arch Linux, вы можете установить rename
пакета из AUR
обеспечивает renamexm
команда as /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
Вы можете принести образец разработчики.mp3 файл из здесь, если нужно ;)
никто не предлагает набор?
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, это может завершиться неудачей, потому что windows не чувствительна к регистру под капотом. Для них добавьте шаг, который mv-это файл с другим именем, например " $old.tmp", затем до $new.
Длительным, Но "Работает Без Сюрпризов И Без Установки"
этот скрипт обрабатывает имена файлов пробелами, кавычками, другими необычно символы и Unicode, работает на нечувствительных к регистру файловых системах и большинстве Unix-y сред которые имеют установленные bash и awk (т. е. почти все). Он также сообщает о коллизиях, если таковые имеются (оставляя имя файла в верхнем регистре) и, конечно, переименовывает файлы и каталоги и работает рекурсивно. Наконец, это очень адаптируемо: вы можете настроить команду find для целевых файлов/dirs, которые вы хотите, и вы можете настроить awk для других манипуляций с именами. Обратите внимание, что под "ручками Unicode" я имею в виду, что он действительно преобразует их случай (не игнорируйте их, как ответы, которые используют tr
).
# adapt the following command _IF_ you want to deal with specific files/dirs
find . -depth -mindepth 1 -exec bash -c '
for file do
# adapt the awk command if you wish to rename to something other than lowercase
newname=$(dirname "$file")/$(basename "$file" | awk "{print tolower($0)}")
if [ "$file" != "$newname" ] ; then
# the extra step with the temp filename is for case-insensitive filesystems
if [ ! -e "$newname" ] && [ ! -e "$newname.lcrnm.tmp" ] ; then
mv -T "$file" "$newname.lcrnm.tmp" && mv -T "$newname.lcrnm.tmp" "$newname"
else
echo "ERROR: Name already exists: $newname"
fi
fi
done
' sh {} +
ссылки
мой скрипт основан на этих отличных ответы:
https://unix.stackexchange.com/questions/9496/looping-through-files-with-spaces-in-the-names