2015-02-13 2 views
0

Я пытаюсь переименовать группу файлов вида:Пакетное переименование нескольких номеров в имени файла с различными заполнения

test1_run1 
test1_run2 
    ... 
test1_run10 
    ... 
test10_run1 
test10_run2 
    ... 
test10_run10 

форме с несколькими отступов. Для первого номера мне нужно заполнение нулями длины 5 и второй с длиной 3.

Конечный результат должен иметь вид:

test00001_run001 
test00001_run002 
    ... 
test00001_run010 
    ... 
test00010_run001 
test00010_run002 
    ... 
test00010_run010 

Как я могу это сделать в Баш для всех файлов в определенной папке?

+2

что вы попробовать? –

+0

Существует несколько тегов для «переименования». Я предложил слить [rename] и [renaming], и вы можете проголосовать (вверх или вниз) в http://stackoverflow.com/tags/rename/synonyms – fedorqui

ответ

1

В Баш:

#!/bin/bash 

shopt -s nullglob extglob 

for file in test+([[:digit:]])_run+([[:digit:]]); do 
    [[ $file =~ ^test([[:digit:]]+)_run([[:digit:]]+)$ ]] 
    printf -v newfile 'test_%05d_run%03d' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))" 
    echo mv "$file" "$newfile" 
done 

Выполнить это внутри папки, которую требуется обработать. Это будет только echo команды mv. Удалите echo, если вы довольны результатом.

  • Мы используем опцию оболочки nullglob, чтобы не совпадающие шары расширялись до нуля;
  • мы используем опцию оболочки extglob, потому что цикл for будет использовать расширенные шары;
  • расширенный глобус test+([[:digit:]])_run+([[:digit:]]) будет расширяться до файлов, соответствующих этому шаблону (если есть)
  • Мы используем регулярное выражение, чтобы получить цифры из имен файлов; первый номер будет в BASH_REMATCH[1], а второй - в BASH_REMATCH[2].
  • мы используем printf для форматирования нового имени файла; модификаторы %05d и %03d будут форматировать номера в соответствии с вашими пожеланиями (с соответствующими ведущими нулями). Обратите внимание, что мы используем ((10#${BASH_REMATCH[1]})), чтобы явно указать, что номер находится в radix 10, если у вас есть файл test09_run001. Часть 09 сделала бы bash неверным истолкованием числа в radix 8 (из-за ведущего 0), и вы получите жалобу; переключатель -v сообщает printf, чтобы он не выводился на стандартный выход, но для сохранения вывода в переменной newfile;
  • окончательно мы делаем mv.
1

Мы можем преобразовать строку в test + 5 digits + _run + 3 digits форматов, говоря:

$ awk -F"test" '{split($2,a,"_run"); printf "%s%0.5d%s%0.3d\n", FS, a[1], "_run", a[2]}' a 
test00001_run001 
test00001_run002 
test00001_run010 
test00010_run001 
test00010_run002 
test00010_run010 

Это работает с использованием test в качестве разделителя полей и разделив 2-ое поле на две части: до и после _run. Затем он использует printf штук, чтобы получить нужный результат.

Затем вы можете распечатать mv вместе с предыдущим значением и сказать:

$ awk -F"test" '{split($2,a,"_run"); printf "mv %s %s%0.5d%s%0.3d\n", $0, FS, a[1], "_run", a[2]}' a 
mv test1_run1 test00001_run001 
mv test1_run2 test00001_run002 
mv test1_run10 test00001_run010 
mv test10_run1 test00010_run001 
mv test10_run2 test00010_run002 
mv test10_run10 test00010_run010 

Если затем конвейер к sh, это будет выполнен.

1

Если вы не хотите использовать Perl или AWK, и строго использовать Баш и некоторые служебные программы, которые доступны в большинстве распределения, вы можете попробовать что-то вроде этого:

for i in * ; do 
    testpart=`echo $i | cut -d_ -f1` 
    testnum=${testpart#test} 
    runpart=`echo $i | cut -d_ -f2` 
    runnum=${runpart#run} 
    destfile=test`printf %05d $testnum`_run`printf %03d $runnum` 

    mv $i $destfile 
done 
Смежные вопросы