Сценарии оболочки (регулярное выражение для перемещения файлов) - PullRequest
2 голосов
/ 16 августа 2011

У меня есть список файлов, таких как:

i60.st082313ea.jpg
i61.st51249c5e.jpg
i62.stef1fe5f2.jpg

Я хотел бы переименовать каждый файл в каталоге, уменьшив начальное целое число (например, 60, 61, 62) на единицу.

Я сделал svn-переименование в оболочке, используя что-то вроде следующего:

for file in *.xml;
    do svn mv $file `basename $file xml`json;
done;

Но когда дело доходит до создания регулярного выражения и вычитания 1 из части файла, я в растерянности. Стоит упомянуть, что файл может иметь выражение i[0-9]+, повторенное в другом месте в имени, поэтому он должен соответствовать только первой строке.

Любая помощь / учебные пособия / ссылки будут по достоинству оценены.

Ответы [ 4 ]

2 голосов
/ 16 августа 2011
for file in *.jpg; do
    newfilename=`echo $file | awk -F '.' '{ OFS=".";print "i" substr($1,2,2)+1, $2, $3}'`
    mv $file $newfilename
done;

ПРИМЕЧАНИЕ это работает только в том случае, если имена файлов соответствуют вашему примеру (например, целые числа находятся на 2-й и 3-й позициях, а файл имеет ровно два . с).

НТН

1 голос
/ 16 августа 2011

Без создания процесса для каждого файла для переименования и в оболочке bash (вы можете узнать, какую оболочку вы используете, набрав команду echo $SHELL), предполагая, что имя вашего файла всегда начинается с 'i', за которым следует номер, за которым следует '.':

ls $.jpg | while read file; do
  post_dot=${file#*.}
  pre_dot=${file%%.*}
  number=${pre_dot#i}
  echo "mv "$file" "i$((number-1)).$post_dot""
done

Если вы довольны результатом печати, удалите 'echo "' в начале и '"' в конце строки mv. '"' вокруг $file и i$((number-1)).$post_dot в команде mv важны для учета пробелов в имени файла.

1 голос
/ 16 августа 2011

Самое замечательное, ваш вклад очень регулярный. Таким образом, используя регулярное выражение, как

^i([0-9]+)(\..*)$

будет начинаться с начала ввода, соответствовать 'i' как необходимому символу, затем соответствовать десятичному числу, а затем совпадать с остальной частью ввода до конца.

Скобки делают группы доступными для захвата совпадений. Если вы используете bash, группы захвата доступны в BASH_REMATCH (массив). С этим регулярным выражением у вас есть две группы захвата: цифры, которые вы хотите уменьшить, и остальная часть имени файла.

Чтобы создать новое имя файла, вы хотите объединить символы 'i', ${BASH_REMATCH[1]} - 1 и ${BASH_REMATCH[2]}.

Если вы не согласны с bash, возможно, попробуйте perl? (Кроме того, вы могли бы использовать \d для цифр, особенно моего фаворита.) Он немного тяжелее на процессоре, чем sed или awk, но гораздо проще для того, что вы пытаетесь сделать.

sed поддерживает обратные ссылки, но для их арифметики вам придется вызывать команду оболочки из выражения sed (выполнимо). awk на самом деле не поддерживает обратные ссылки, но gawk имеет функцию, чтобы помочь, gensub.

0 голосов
/ 14 октября 2014

Я написал небольшой скрипт, который я называю mv_re, хотя, возможно, mv_eval или mv_perl будет иметь больше смысла:

 #!/usr/bin/perl

 foreach (@ARGV) {
    push(@evals,$_);
 }

 sub mv_eval {
     my ($dirname) = @_;
     opendir (my($dh), $dirname) or
         die "Couldn't open dir '$dirname': $!";
     my @fs = readdir $dh;
     foreach $f (@fs) {
         $_ = $f;
         foreach $e (@evals) { eval $e; }
         print "mv '$f' '$_'\n" if ($_ ne $f);
     }
     closedir $dh;
 }

 mv_eval(".");

Он обрабатывает каждый аргумент как строку кода на Perl и запускает ихкаждое имя файла в текущем напрямую.Любые измененные имена файлов печатаются соответствующими командами mv.Поэтому mv_re s/www.// пишет скрипт для удаления первых www. из каждого файла в текущем каталоге.

В идеале я должен добавить необязательные аргументы командной строки для каталога или спецификацию файлов, альтернативные команды для mv,и возможность просто сделать это, а не писать пользователю сценарий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...