Переименование папок, файлов и подпапок в bash

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

find . -depth -iname \* -exec mv {} `echo {} | tr [:upper:] [:lower:]` \;

Какие-либо предложения? Спасибо


person Ant4res    schedule 16.11.2011    source источник


Ответы (2)


Почему бы не использовать простой цикл while:

find testdir/ -depth | while read file; do NEWNAME=$(dirname "$file")/$(echo $(basename "$file") | tr '[:lower:]' '[:upper:]'); mv "$file" "$NEWNAME"; done
person johnbaum    schedule 16.11.2011
comment
Я пытался использовать ваш первый скрипт, но он меняет только первый уровень дерева папок. Если у меня есть, например, DocumentsFolder-JobFolder-Test.txt, после выполнения у меня будет DOCUMENTFOLDER-JobFolder-Test.txt. Я хочу использовать верхний регистр для всех папок, подпапок и файлов, например DOCUMENTFOLDER-JOBFOLDER-TEST.TXT. - person Ant4res; 16.11.2011

Проблема в том, что ваша команда в обратных кавычках, echo {} | tr [:upper:] [:lower:], сначала раскрывается оболочкой, поэтому то, что find на самом деле видит в качестве аргументов,

find . -depth -iname \* -exec mv {} {} \;

(Выполнение tr [:upper:] [:lower:] на входе {} просто возвращает вам {} обратно).

Вот один обходной путь с использованием подоболочки в качестве команды -exec:

find . -mindepth 1 -depth -iname \* -exec \
    sh -c 'mv "$0" "`tr \[:upper:\] \[:lower:\] <<<"$0"`"' {}  \;

или более читабельно, используя синтаксис $():

find . -mindepth 1 -depth -iname \* -exec \
    sh -c 'mv "$0" "$(tr "[:upper:]" "[:lower:]" <<<$0)"' {}  \;

Обратите внимание, что вам также необходимо заключить в кавычки tr диапазонов символов, чтобы оболочка не расширяла их!

Также рекомендуется добавить -mindepth 1, чтобы не возникало ошибки при попытке запустить mv . ..

person Community    schedule 16.11.2011
comment
Спасибо за объяснение ... Я попытался запустить скрипт, но получил много синтаксических ошибок и никаких изменений в подпапках и именах файлов. - person Ant4res; 16.11.2011
comment
Похоже, вы получили ответ другим способом, но, к сведению, исходный код не работал должным образом с именами файлов с пробелами, что может быть проблемой. Я исправил это сейчас. Как только вы доберетесь до этого количества уровней цитирования, решение цикла действительно начнет выглядеть довольно хорошо ;-) - person ; 17.11.2011
comment
Спасибо за Ваш ответ! Но что означает ‹‹‹$0? - person Ant4res; 17.11.2011
comment
<<< в bash создает строку здесь, что означает, что любое слово, следующее за ним, становится стандартным вводом команды, точно так же, как some-command <some-file делает содержимое some-file стандартным вводом). Например, попробуйте tr a-z A-Z <<<"a test string". В этом случае <<<$0 принимает первый аргумент, $0, в sh -c ... — имя файла, которое find передает, заменяя {}, — и делает его входным для tr .... (Кстати, обычно первый аргумент скрипта — $1, но sh -c ведет себя по-другому — см. руководство по Bash). - person ; 17.11.2011