2009-05-19 7 views
19

Я изначально был набор изображений вида IMAGE_001.jpg, image_002.jpg, ...Переименование набора файлов 001, 002, ... на Linux

Я прошел через них и удалить несколько , Теперь я хотел бы переименовать оставшиеся файлы обратно в image_001.jpg, image_002.jpg, ...

Есть ли команда Linux, которая будет делать это аккуратно? Я знаком с переименованием, но не вижу ничего, чтобы заказать имена файлов, подобные этому. Я думаю, что с ls *.jpg списки файлов в порядке (с пробелами), решение было бы передать вывод этого в цикл bash или что-то еще?

ответ

12

Если я правильно понимаю, у вас есть, например, image_001.jpg, image_003.jpg, image_005.jpg, и вы хотите переименовать в image_001.jpg, image_002.jpg, image_003.jpg.

EDIT: Это изменение, чтобы поместить временный файл в текущий каталог. Как отметил Stephan202, это может существенно повлиять, если temp находится в другой файловой системе. Для того, чтобы избежать попадания в временный файл в цикле, теперь проходит через изображение *

i=1; temp=$(mktemp -p .); for file in image* 
do 
mv "$file" $temp; 
mv $temp $(printf "image_%0.3d.jpg" $i) 
i=$((i + 1)) 
done          
+0

Nice (до тех пор, пока mktemp создает файл на том же томе, в противном случае переход во временный подкаталог выполняется быстрее) – Stephan202

+0

Хорошая точка. Это можно решить с помощью mktemp -p. –

+0

Я собираюсь отметить это как ответ, но мне не нужно было использовать временную директорию: мои изображения фактически начинались с 002 (с пробелами), поэтому конфликтов не было. 002 переименовывается в 001, 005-> 002, 006-> 003 и так далее. – DisgruntledGoat

1

Это делает обратное, что вы просите (принимая файлы вида * .jpg.001 и преобразование их в * .001.jpg), но может быть легко модифицирован для вашей цели:

for file in * 

do 

if [[ "$file" =~ "(.*)\.([[:alpha:]]+)\.([[:digit:]]{3,})$" ]] 

then 

mv "${BASH_REMATCH[0]}" "${BASH_REMATCH[1]}.${BASH_REMATCH[3]}.${BASH_REMATCH[2]}" 

fi 

done 
9

Простого цикла (тест с echo, выполнить с mv):

I=1 
for F in *; do 
    echo "$F" `printf image_%03d.jpg $I` 
    #mv "$F" `printf image_%03d.jpg $I` 2>/dev/null || true 
    I=$((I + 1)) 
done 

(я добавил 2>/dev/null || true для подавления предупреждений об идентичных исходных и целевых файлах Если это не по своему вкусу, пойти с Matthew Flaschen «s 4444027924111294. 399646466818888.)

+0

Это будет работать .. – Louis

+0

Это не работает. У большинства изображений все равно будут свои оригинальные имена, поэтому mv не удастся. –

+0

@ Матвей: хорошее место. Теперь изменился код, чтобы все файлы были перемещены во временный каталог. – Stephan202

0

Я собирался предложить что-то вроде выше, используя для цикла, итератор, вырезать -f1 -d «_», то mv i iiterator. Похоже, что это уже покрыто другими способами.

1

Несколько хороших ответов здесь уже; но некоторые полагаются на скрытые ошибки, которые не являются хорошей идеей (предполагается, что mv будет только ошибкой из-за ожидаемого условия - как насчет всех других реалов mv может быть ошибкой?).

Кроме того, это может быть сделано немного короче и должен быть лучше цитируемый:

for file in *; do 
    printf -vsequenceImage 'image_%03d.jpg' "$((++i))" 
    [[ -e $sequenceImage ]] || \ 
     mv "$file" "$sequenceImage" 
done 

Также отметим, что you shouldn't capitalize your variables в Баш сценариев.

+1

В последних версиях bash вы можете использовать: printf -vsequenceImage 'image_% 03d.jpg' $ ((++ i)) –

+0

На самом деле, вы манипулируете переменной i в подоболочке, поэтому в вашем примере это не увеличивается. –

+0

radoulov: хорошо пятнистый, спасибо. Я согласен, я должен проверить, что я пишу. – lhunath

2

Попробуйте следующий сценарий:

numerate.sh

Этот код отрезала должен делать эту работу:

./numerate.sh -d <your image folder> -b <start number> -L 3 -p image_ -s .jpg -o numerically -r 
Смежные вопросы