Я должен переименовать набор файлов, используя rename
команда (с регулярным выражением).
После некоторых попыток я не могу найти выражение, которое дает ожидаемый результат.
У меня есть такой файл:
prefix_ некоторое_имя _other.txt
Все файлы начинаются с " prefix_
"строка и конец" _other.txt
»,
и некоторое_имя часть может состоять из нескольких (буквенно-цифровых) слов
разделены подчеркиванием.
Так что возможно иметь:
prefix_one_name_other.txt
prefix_this_is_my_name_1_this1_other.txt
Мне нужно переименовать имена файлов, как эти:
other_one-name_ Дата и время other_this-это-мое имя-1-this1_ Дата и время
Другими словами:
- Надо удалить
prefix
"(оставляя подчеркивание) - "
other
"токен переходит в начало имени файла - В некоторое_имя преобразуйте подчеркивание (_) в тире (-)
- Подчеркивание в конце имени файла (после некоторое_имя ) должен остаться
- Нужно удалить
.txt
расширение, заменено Дата и время ,
Что я пробовал:
rename 's/fw_([a-z]+)_(\d)_(\w+\d)_(\w+)\.txt/$4_$1-$2-$3_'$datahora'/' *.txt
$datahora
имеет Дата и время значение (проверено). Это работает как ожидалось с
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
Вариант записывается только один раз на диск.
¿Что вы думаете об этих двух решениях? ...
Еще раз спасибо.
Ответы:
Если только ваш
rename
может принимать несколько команд замещения а также корень имени файла (some_name
) может содержать более одного подчеркивания, вы должны сделать это в два этапа: а) заменить подчеркивание тире и б) (пере) переместить фрагменты в именах файлов.Регулярные выражения, которые вы ищете, могут быть, например:
Первый делает подчеркивание для черточных переводов, в то время как последний меняет местами корень и суффикс и добавляет содержимое
DATETIME
переменная окружения для имен. И опускает префикс и расширение, конечно.[^-]*
part соответствует любой строке, не содержащей тире. Если суффикс всегда один и тот же, вы можете дословно поставить его там, как в случае с префиксом (и наоборот - если префикс может меняться, используйте^[^-]*-
сопоставить его с любой строкой, не содержащей тире, расположенной между началом имени файла и (таким образом) первым тире).Если твой
rename
поддерживает несколько команд, просто объедините их:источник
other-this-is-1-name-20140717-093458
Когда я ищу:other_this-is-1-name_20140717-093458
Обратите внимание на подчеркивание послеother
и до даты и времени.$2
с подчеркиванием во втором регулярном выражении.