Я должен переименовать набор файлов, используя команду rename
(с регулярным выражением).
После некоторых попыток я не могу найти выражение, которое дает ожидаемый результат.
У меня есть такой файл:
prefix_some_name_other.txt
Все файлы начинаются со строки « prefix_
» и заканчиваются « _other.txt
», а часть some_name может состоять из нескольких (буквенно-цифровых) слов, разделенных подчеркиванием.
Так что возможно иметь:
prefix_one_name_other.txt
prefix_this_is_my_name_1_this1_other.txt
Мне нужно переименовать имена файлов, как эти:
other_one-name_datetime other_this-is-my-name-1-this1_datetime
Другими словами:
- Необходимо удалить «
prefix
» (оставив подчеркивание) - «
other
» токен идет в начало имени файла - В some_name преобразуйте подчеркивание (_) в тире (-)
- Подчеркивание в конце имени файла (после some_name) должно оставаться
- Нужно удалить расширение
.txt
, заменить на datetime.
Что я пробовал:
rename 's/fw_([a-z]+)_(\d)_(\w+\d)_(\w+)\.txt/$4_$1-$2-$3_'$datahora'/' *.txt
$datahora
имеет значение datetime (проверено). Это работает как ожидалось с
prefix_name_1_gnt1_other.txt
но не с
prefix_other_name_2_gnt2_other.txt
Где я неправ? Как еще я мог сделать это?
Я повесил свой разум, так как на данный момент я не могу найти регулярное выражение, которое работает для всех имен файлов, которые у меня есть. Я знаю, что первым элементом в строке всегда является prefix
часть, а последним элементом является other.txt
часть строки. Так что можно разбить строку на массив и получить элементы, которые мне нужны для построения нового имени. На самом деле как то так.
datahora="20140718-080000"
arrfiles=( *.txt )
for curfile in ${arrfiles[*]}
do
arrparts=( ${curfile//_/ } )
numitems=${#arrparts[*]}
newname=""
for (( c=1; c<numitems-1; c++ ))
do
newname+="${arrparts[c]}-"
done
newname=${newname%-}
arrparts[numitems-1]=${arrparts[numitems-1]/.txt/}
newname="${arrparts[numitems-1]}_${newname}_$datahora"
echo "$curfile pasa a $newname"
mv ${curfile} ${newname}
done
После того, как все сделано таким образом, я еще раз попробовал предложение @peterph и, наконец, сделал несколько переименованных комбинаций регулярных выражений. Примерно так:
rename 's/_/-/g' *.txt
rename 's/^fw-(.*)-([^-]*)(\.txt)/$2.$1$3/' *.txt
rename 's/(\w+)\.(.*)(\.txt)/$1_$2_'$datahora'/' *.txt
Я не уверен, что лучший подход. На мой взгляд, вариант регулярного выражения кажется более элегантным, но мне нужно три операции переименования (трижды получить доступ к диску), чтобы выполнить эту работу, в то время как вариант array
записывает на диск только один раз.
¿Что вы думаете об этих двух решениях?...
Еще раз спасибо.