У меня есть куча файлов, которые я хотел бы переименовать. Их имена имеют следующий формат:
p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j
Перед каждым уникальным именем файла стоит префикс. В этом случае этот префикс начинается с буквы p
и имеет после себя число, p
увеличивающееся на единицу. Точка ( .
) отделяет префикс от уникального имени файла. После каждого уникального имени файла стоит суффикс, начинающийся с хэштега ( #
). Я хотел бы удалить префиксы до точек включительно, а также суффиксы, начинающиеся с хэштегов включительно. Я хотел бы, чтобы в результате получались только уникальные имена файлов между точками и хэштегами, например:
uniquenameA
uniquenameB
uniquenameC
uniquenameD
uniquenameE
uniquenameF
uniquenameG
uniquenameH
uniquenameI
uniquenameJ
Я новичок в написании скриптов, поэтому, если бы вы могли объяснить, как работает код, в дополнение к предоставлению самого кода, я был бы очень признателен.
решение1
Если у вас есть perl
версия rename
(иногда ранее называвшаяся prename
), вы можете применить замену регулярного выражения:
rename -n 's/^.*?\.(.*?)#.*/$1/' *
Если вы не понимаете регулярные выражения (RE), их стоит изучить.
s/xx/yy/
-xx
заменитьyy
^
- соответствие неявному началу строки.*?
- сопоставьте как можно более короткую строкуноль или более символов чего-либопри условии соответствия остальной части шаблона\.
- сопоставить буквальную точку.
(.
символ представляетчто-либо, но\.
это буквальная точка)(
...)
сопоставить шаблон внутри скобок и присвоить ему номер соответствия 1..9; позже на него ссылается$1
(второй(
...)
будет$2
, и т.д.)#
- буквальный характер.*
- самый длинный матч, который естьноль или более символов чего-либо(.
эточто-либои*
означает _ноль или более предыдущего пункта)
Удалите -n
("никаких действий"), когда вас все устроитбыработа. Замените его на , -v
чтобы увидеть, что на самом деле происходит, или просто опустите его для бесшумной работы.
решение2
Вот awk
скрипт, который выполняет эту задачу:
Только для печати/отладки:
awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){print "mv "$0" "m[2] }' input.txt
Сделайте переименование:
awk 'match($0,/(^[^\\.]+.)([^#]+)/,m){system("mv "$0" "m[2])}' input.txt
ввод.txt
p1.uniquenameA#blah_a
p2.uniquenameB#blah_b
p3.uniquenameC#blah_c
p4.uniquenameD#blah_d
p5.uniquenameE#blah_e
p6.uniquenameF#blah_f
p7.uniquenameG#blah_g
p8.uniquenameH#blah_h
p9.uniquenameI#blah_i
p10.uniquenameJ#blah_j
выход
mv p1.uniquenameA#blah_a uniquenameA
mv p2.uniquenameB#blah_b uniquenameB
mv p3.uniquenameC#blah_c uniquenameC
mv p4.uniquenameD#blah_d uniquenameD
mv p5.uniquenameE#blah_e uniquenameE
mv p6.uniquenameF#blah_f uniquenameF
mv p7.uniquenameG#blah_g uniquenameG
mv p8.uniquenameH#blah_h uniquenameH
mv p9.uniquenameI#blah_i uniquenameI
mv p10.uniquenameJ#blah_j uniquenameJ
решение3
Вот решение с использованиемsed
for i in *
do
mv $i $( echo $i | sed 's/p[[:digit:]]*\.\([^#]*\)\#.*/\1/' )
done
Место назначения создается с помощью sed
поиска a, p
за которым следует любое количество цифр, за которыми следует точка. Символы от точки и далее до #
символа являютсявспомнилв регистр, а все имя файла заменяется навспомнилперсонажи.