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

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

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

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

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

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

Ответы [ 27 ]

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

Вот мое неоптимальное решение с использованием сценария bash Shell:

#!/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 внутри этой папки все еще переименовываются).

Edit: так как «find -depth» и «find | sort -r» оба возвращают список папок в порядке, пригодном для переименования, я предпочел использовать «-depth» для поиска папок.

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

Это небольшой сценарий оболочки, который делает то, что вы просили:

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

Обратите внимание на действие -depth в первой находке.

2 голосов
/ 22 февраля 2016
for f in `find -depth`; do mv ${f} ${f,,} ; done

find -depth печатает каждый файл и каталог, а содержимое каталога печатается перед самим каталогом. ${f,,} строчные буквы имени файла.

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

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

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

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

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

2 голосов
/ 07 апреля 2018

с MacOS,

Установите пакет rename,

brew install rename

Используйте

find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"                       

Эта команда находит все файлы с расширением *.py и преобразует имена файлов в нижний регистр.

`f` - forces a rename

Например,

$ find . -iname "*.py" -type f
./sample/Sample_File.py
./sample_file.py
$ find . -iname "*.py" -type f | xargs -I% rename -c -f  "%"
$ find . -iname "*.py" -type f
./sample/sample_file.py
./sample_file.py
1 голос
/ 31 января 2016

В этой ситуации я хотел бы использовать 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])
1 голос
/ 25 марта 2015

В 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
1 голос
/ 18 июля 2013

Не переносимо, только Zsh, но довольно лаконично.

Сначала убедитесь, что загружено zmv.

autoload -U zmv

Также убедитесь, что extendedglob включено:

setopt extendedglob

Тогда используйте:

zmv '(**/)(*)~CVS~**/CVS' '${1}${(L)2}'

Для рекурсивных строчных файлов и каталогов, имя которых не CVS .

1 голос
/ 09 мая 2019

Самый простой подход, который я нашел в MacOSX, заключался в использовании пакета переименования из http://plasmasturm.org/code/rename/:

brew install rename
rename --force --lower-case --nows *

- принудительно переименовывать, даже если файл с именем назначения уже существует.

- строчные буквы. Преобразование имен файлов во все строчные.

- теперь Заменить все последовательности пробелов в имени файла символами подчеркивания.

1 голос
/ 24 сентября 2018

Длительный, но "Работает без сюрпризов и без установок"

Этот скрипт обрабатывает имена файлов с пробелами, кавычками, другими необычными символами и Unicode, работает с нечувствительными к регистру файловыми системами и большинством сред Unix-y , в которых установлены bash и awk (т.е. почти все). Он также сообщает о коллизиях, если таковые имеются (оставляя имя файла в верхнем регистре), и, конечно, переименовывает файлы и каталоги и работает рекурсивно. Наконец, он легко адаптируется: вы можете настроить команду find для выбора нужных вам файлов / каталогов и настроить 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

Как преобразовать строку в нижний регистр в Bash?

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