Пакетное переименование с использованием сценария оболочки - PullRequest
3 голосов
/ 22 августа 2010

У меня есть папка с файлами с именем

input (1).txt
input (2).txt
input (3).txt
...
input (207).txt

Как мне переименовать их в

input_1.in
input_2.in
input_3.in
...
input_207.in

Я пытаюсь это

for f in *.txt ; do mv $f `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done

Но это дает мне

mv: target `(100).txt' is not a directory
mv: target `(101).txt' is not a directory
mv: target `(102).txt' is not a directory
...

Где я ошибся?


Я поместил в кавычки сейчас, но я получаю это сейчас

mv: `input (90).txt' and `input (90).txt' are the same file

Он как-то пытается переименовать файл с тем же именем. Как это происходит?

Ответы [ 6 ]

3 голосов
/ 22 августа 2010

нет необходимости вызывать внешние команды

#!/bin/bash
shopt -s nullglob
shopt -s extglob
for file in *.txt
do
  newfile="${file//[)]/}"
  newfile="${file// [(]/_}"
  mv "$file" "${newfile%.txt}.in"
done
3 голосов
/ 22 августа 2010

Это потому, что bash for разделил элемент пробелом '', и вы приказали ему переместить 'input' в '(1)'.

Чтобы решить эту проблему, нужно сказатьbash для разделения на новую строку с использованием переменной IFS.

Пример:

IFS=$'\n'

Затем выполните команду.

Однако я предлагаю вам использовать find чтобы сделать это вместо этого, используя команду -exec.

Например:

find *.txt -exec mv <b>"{}"</b> `echo <b>"{}"</b> | sed -e 's/input\ (\([0-9]*\))\.txt/input_\1.in/'` <b>\;</b>

ПРИМЕЧАНИЕ. Я пишу это из памяти и проверил, так что давайте попробуем настроить его.*

Надеюсь, это поможет.

3 голосов
/ 22 августа 2010

Вы забыли процитировать свои аргументы.

... mv "$f" "$(echo "$f" | ... )" ; done
1 голос
/ 23 августа 2010

Как вы уже исправили, вам нужно заключить аргумент $f в mv.

Что касается вашей второй проблемы, sed не поддерживает \d. Вы можете использовать [0-9] вместо.

0 голосов
/ 22 августа 2010

Если у вас установлена ​​GNU Parallel http://www.gnu.org/software/parallel/, вы можете сделать это:

seq 1 207 | parallel -q mv 'input ({}).txt' input_{}.in

Посмотрите вступительное видео для GNU Parallel, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ

0 голосов
/ 22 августа 2010
for f in *.txt ; do mv "$f" `echo $f | sed -e 's/input\ (\(\d*\))\.txt/input_\1.in/'` ; done
...