2014-11-11 5 views
2

Я бы хотел заменить :2f на - во всех именах файлов/файлов, и по какой-то причине однострочный снизу не работает, есть ли более простой способ достичь этого?BASH: найти и переименовать файлы и каталоги

Справочник имя Пример:

AN :2f EXAMPLE 

Команда:

for i in $(find /tmp/ \(-iname ".*" -prune -o -iname "*:*" -print \)); do { mv $i $(echo $i | sed 's/\:2f/\-/pg'); }; done 
+1

'for' не перекрывает строки с нулевым символом. –

+0

Почему вы используете '-prune' здесь? вы не хотите переименовывать скрытые файлы/каталоги? или просто пропустить '.'? –

+0

Я просто хочу пропустить скрытые файлы и директории. – HTF

ответ

2

Вам не нужно разобрать вывод find:

find . -depth -name '*:2f*' -execdir bash -c 'echo mv "$0" "${0//:2f/-}"' {} \; 

Мы используем -execdir так, что команда выполняется из каталога, содержащего найденный файл. Мы также используем -depth, чтобы содержимое каталога рассматривалось перед самим каталогом. Все это, чтобы избежать проблем, если строка :2f появляется в имени каталога.

Как есть, эта команда безвредна и не будет выполнять никакого переименования; он будет показывать только на терминале, что будет сделано. Удалите echo, если вы довольны тем, что видите.

Предполагается, что вы хотите выполнить переименование для всех файлов и папок (рекурсивно) в текущем каталоге.

-execdir может быть недоступен для вашей версии find.

Если ваш find не поддерживает -execdir, вы можете обойтись без, как так:

find . -depth -name '*:2f*' -exec bash -c 'dn=${0%/*} bn=${0##*/}; echo mv "$dn/$bn" "$dn/${bn//:2f/-}"' {} \; 

Здесь хитрость заключается в том, чтобы отделить часть каталога от имени файла часть-это то, что мы храним в dn (dirname) и bn (basename), а затем только изменить значение :2f в имени файла.

+0

Спасибо, не могли бы вы также объяснить эту часть кода: '' $ {0 //: 2f/-} "', не могли бы вы указать мне некоторые руководства BASH для этого бита? – HTF

+0

@HTF: вы найдете информацию об этом в разделе [_Shell Parameter Expansion_ в Справочном руководстве Bash] (http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion). –

+0

Я получаю следующую ошибку: 'bash: ошибка при загрузке разделяемых библиотек: libtinfo.so.5: невозможно открыть файл общих объектов: Ошибка 24'. Знаете ли вы, есть ли способ передать его на 'xargs' для преодоления предела открытых файлов? – HTF

1

Поскольку у вас есть имена файлов, содержащие пространство, for разделит их на отдельные аргументы, когда итерация. Труба к промежуточной петле вместо:

find /tmp/ \(-iname ".*" -prune -o -iname "*:*" -print \) | while read -r i; do 
    mv "$i" "$(echo "$i" | sed 's/\:2f/\-/pg')" 

Также укажите все переменные и подстановки команд.

Это будет работать до тех пор, пока у вас нет имен файлов, содержащих новую строку.

+0

Это все еще не работает. Я боюсь. – HTF

Смежные вопросы