Попытка сделать арифметику в инструменте переименования Perl (Debian)

8

Предположим, у меня есть пять mp3-файлов:

01-trackfoo.mp3
02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
05-trackxyz.mp3

Теперь я быстро прослушиваю файлы (просто mplayer на консоли справится с задачей) и обнаруживаю, что треки расположены в неправильном порядке . 05 на самом деле 02, а остальные должны быть переименованы. Итак, сначала я сделаю временное переименование:

01-trackfoo.mp3

02-trackbar.mp3
03-trackbaz.mp3
04-trackabc.mp3
00-trackxyz.mp3

Теперь нам нужно «смещение»: 02 должно стать 03, 03 должно стать 04 и 04 должно стать 05. Чтобы минимизировать путаницу, ex-05 (теперь 00) будет mvиздан позже.

Мой подход был такой: (perl rename, Larry Wall, по умолчанию здесь, в Debian)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/' *

а также (позже, после еще нескольких RTFM'ing)

rename 's/0([2-4])([\s\S]+)/0($1+1)$2/e' *

Ни один из них не сработал, особенно потому, что /e[val]модификатор не принимает ничего, кроме оценок, и выдаст ошибку, когда вы попытаетесь объединить оценки со строками. bashМожет сделать это просто отлично, например , foo$((1+6))будет оцениваться с foo7.

Итак, как я могу это сделать (предпочтительнее, одной строкой, не собираясь писать целый автономный скрипт только для этого)?

ошибка синтаксиса
источник

Ответы:

7

У тебя почти было это. Вам просто нужно сделать явные строки и конкатенацию строк явным образом в /eподстановке -modified, используя кавычки и оператор точки.

rename 's/0([2-4])([\s\S]+)/"0".($1+1).$2/e' *
Алан Карри
источник
Он оставляет исходный 05 еще не переименованным, но +1 для разрешения однострочного сбоя.
Peter.O
1
(минорная нота, переименование называется prename в Ubuntu) ... Если имен в стартах каталога с $'\x01'2затем предварительным переименованием , как это: prename 's/^05/\x012/' 05*.. то выше [2-4]переименование .. тогда окончательным prename 's/^\x01/0/' $'\x01'2*будет делать трюк .. Это не делает 3 один -liners ... В-четвертых, и начальная проверка возможного присутствия файла, начинающегося с $'\x01', что-то вроде этого фрагмента bash будет его заманивать в ловушку ..shopt -s nullglob; x=($'\x01'*); [[ -n $x ]] && { echo '\x01' is not suitable; exit; }
Peter.O
YEEES! Спасибо, Алан, я не думал об этом точечном операторе, хотя я знал, что делать в понятных человеку словах: «скажи / не трогать вещи за пределами ()» :) И спасибо Питеру за удар подход также. Кроме того, если бы я имел представление о том, насколько близок синтаксис PHP к Perl, я бы, вероятно, нашел решение методом проб и ошибок. Потому что эта точка является аналогом JavaScript '+' в PHP для конкатенации строк.
синтаксическая ошибка
4

предпочтение отдается одной строке, не предназначенной для написания всего отдельного сценария только для этого

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

Для такой мелочи, как правило, я начинаю пытаться решить ее в Bash:

#!/bin/bash
if [ -z "$1" ] ; then echo Need arguments. ; exit 1 ; fi

typeset -i i=1
for f in "$*"
do
    tailbits=`echo "$f" | sed -e 's/^[0-9]+//'`
    mv "$f" sertmp-`printf %02d $i`"$tailbits"
    i=i+1
done

for f in "sertmp-*"
do
    mv "$f" `echo "$f" | sed -e s/^sertmp-//` 
done

По сути, этот сценарий удаляет все начальные цифры, а затем помещает увеличивающийся серийный номер, дополненный нулями, на лицевой стороне, а файлы нумеруются в соответствии с порядком их передачи в сценарий.

Он делает это в два этапа, с sertmp-префиксами для первого прохода, чтобы избежать любого риска конфликтов имен. Если вы вызываете этот скрипт mp3-renamerи называете его так:

$ mp3-renamer 01-foo.mp3 03-bar.mp3 04-qux.mp3

вы сталкиваетесь с тривиальным столкновением при первом переименовании, если вы не используете 2 прохода для переименования. ( 01-foo.mp3-> 01-foo.mp3.)

Если вы называете это так, хотя:

$ mp3-renamer 02-foo.mp3 01-foo.mp3

вы случайно удалили 01-foo.mp3в первом переименовании с переименованием в 1 проход.

Если проблема усложняется, я бы переписал ее на Perl. В этот момент вы можете использовать хеш для хранения старого-> нового сопоставления имен и использовать немного умного кода, чтобы определить правильный порядок выполнения переименований, чтобы избежать необходимости в 2 прохода.

Уоррен Янг
источник