2013-05-14 4 views
41

У меня есть файлы, такие как a_dbg.txt, b_dbg.txt ... в системе Suse 10. Я хочу написать сценарий оболочки bash, который должен переименовать эти файлы, удалив из них «_dbg».Найти несколько файлов рекурсивно и переименовать в linux

Google предложил мне использовать команду rename. Поэтому я выполнил команду rename _dbg.txt .txt *dbg* на CURRENT_FOLDER

My actual CURRENT_FOLDER содержит следующие файлы.

CURRENT_FOLDER/a_dbg.txt 
CURRENT_FOLDER/b_dbg.txt 
CURRENT_FOLDER/XX/c_dbg.txt 
CURRENT_FOLDER/YY/d_dbg.txt 

После выполнения команды rename,

CURRENT_FOLDER/a.txt 
CURRENT_FOLDER/b.txt 
CURRENT_FOLDER/XX/c_dbg.txt 
CURRENT_FOLDER/YY/d_dbg.txt 

Ее не делать рекурсивно, как сделать эту команду для переименования файлов во всех подкаталогах. Как XX и YY У меня будет так много подкаталогов, имя которых непредсказуемо. А также мои CURRENT_FOLDER также будут иметь некоторые другие файлы.

+3

Я получаю 'Bareword "..." не допускается в то время как "строгие подлодки" используются в (Eval 1) линия 1.' –

ответ

82

Вы можете использовать find, чтобы найти все соответствующие файлы рекурсивно:

$ find . -iname "*dbg*" -exec rename _dbg.txt .txt '{}' \; 

EDIT: что '{}' и \; есть?

Аргумент -exec позволяет найти выполнение rename для каждого найденного файла соответствия. '{}' будет заменен именем пути к файлу. Последний токен \; существует только для обозначения конца выражения exec.

Все, что описано красиво на странице человека для находки:

-exec utility [argument ...] ; 
     True if the program named utility returns a zero value as its 
     exit status. Optional arguments may be passed to the utility. 
     The expression must be terminated by a semicolon (``;''). If you 
     invoke find from a shell you may need to quote the semicolon if 
     the shell would otherwise treat it as a control operator. If the 
     string ``{}'' appears anywhere in the utility name or the argu- 
     ments it is replaced by the pathname of the current file. 
     Utility will be executed from the directory from which find was 
     executed. Utility and arguments are not subject to the further 
     expansion of shell patterns and constructs. 
+0

@kamituel Спасибо. Я изучаю linux и использую find несколько раз, мне было интересно, что это значит. спасибо за хорошее объяснение. Можете ли вы рассказать, что? и можем ли мы использовать указанную команду (In Centos 7) как 'find. -type f "* dbg *" -exec переименовать "_dbg.txt" ".txt" * {} \; ' –

+0

Я проверил его и работает только с файлами, не входящими в каталоги. –

+0

Я получил эту ошибку несколько раз: 'Неверная восьмеричная цифра '9' (код пользователя), в конце строки. Я пробовал как одинарные кавычки, двойные кавычки, так и без кавычек для аргументов 'rename'. В частности, я пытаюсь заменить '0123-MISC' на' 0123_AB_MISC'. это моя команда 'find. -iname "* 0123-MISC *" -exec переименовать 0123-MISC 0123_AB_MISC {} \; ' – Eddy

10

с Башем:

shopt -s globstar nullglob 
rename _dbg.txt .txt **/*dbg* 
+3

Отличное решение. Мне пришлось включить эти параметры bash с помощью 'shopt -s globstar nullstar'. Для инструмента переименования, установленного с помощью 'brew install rename' на MacOS, мне пришлось делать' rename -s oldStuff newStuff **/* ' –

9

небольшим скриптом я написал, чтобы заменить все файлы с расширением .txt на .cpp расширения под/tmp и подкаталоги рекурсивно

#!/bin/bash 

for file in $(find /tmp -name '*.txt') 
do 
    mv $file $(echo "$file" | sed -r 's|.txt|.cpp|g') 
done 
+5

Broken method! не делайте 'для файла в $ (find ...)'. См. [Почему вы не должны анализировать вывод ls (1)] (http://mywiki.wooledge.org/ParsingLs). –

1

Сцена выше может быть написана одной строкой:

find /tmp -name "*.txt" -exec bash -c 'mv $0 $(echo "$0" | sed -r \"s|.txt|.cpp|g\")' '{}' \; 
+3

-bash: синтаксическая ошибка возле неожиданного токена ') ' – Steven

+0

@steven попробуйте использовать этот find. -name "* .txt" -exec bash -c 'mv $ 0 $ (echo "$ 0" | sed -r "s/.txt/.cpp/g")' '{}' \; – xxbinxx

-3

классическое решение:

for f in $(find . -name "*dbg*"); do mv $f $(echo $f | sed 's/_dbg//'); done 
+3

Это полностью сломан. Пожалуйста, не делай этого. –

+0

'~/tmp $ mkdir a && cd a/&& touch 1_dbg.txt && cd ..' ' ~/tmp $ для f в $ (find -name "* dbg *"); do mv $ f $ (echo $ f | sed 's/_dbg //'); done' '~/tmp $ cd a/ ~/tmp/a $ l всего 8 drwxrwxr-x 2 repu1sion repu1sion 4096 17 сен 21:17. drwxrwxr-x 3 repu1sion repu1sion 4096 Sep 17 21:17 .. -rw-rw-r-- 1 repu1sion repu1sion 0 сен 17 21:17 1.txt' – pulse

+1

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

0

Если вы хотите переименовать, и не возражаю, используя внешний инструмент, то вы можете использовать rnm. Команда будет:

#on current folder 
rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' * 

-dp -1 сделает рекурсивный для всех подкаталогов.

-fo подразумевает режим только файла.

-ssf '_dbg' ищет файлы с _dbg в имени файла.

-rs '/_dbg//' заменяет _dbg пустой строкой.

Вы можете запустить выше команду с пути CURRENT_FOLDER тоже:

rnm -dp -1 -fo -ssf '_dbg' -rs '/_dbg//' /path/to/the/directory 
8

Для переименования рекурсивно я использую следующие команды:

find -iname \*.* | rename -v "s/ /-/g" 
+0

Также полезно восстановить файлы резервных копий. 'find -iname \ *. * | переименовать -v -f "s/\. bak // g" ' – Paolo

0

Вы можете использовать это ниже.

rename --no-act 's/\.html$/\.php/' *.html */*.html 
Смежные вопросы