
У меня есть следующий набор файлов
top_axi_256_wrapper_05.02.01.14.00_sample06.tgz
top_axi_128_wrapper_05.02.01.14.00_sample06.tgz
Я хочу заменить 05.02.01.14.00
часть на 05_02_01_14_00
. Так что конечный результат — это следующие переименованные файлы
top_axi_256_wrapper_05_02_01_14_00_sample06.tgz
top_axi_128_wrapper_05_02_01_14_00_sample06.tgz
Мой каталог также может содержать следующие типы имен файлов.
a72_a_0.0.0_0.00.04_ac_dc.tgz
Здесь я хочу переименовать файл в
a53_1c_256K_a_0_0_0_0_00_04_ac_dc.tgz
Как это сделать?
решение1
По сути, вам нужно заменить точку на подчеркивание, за исключением последней.
Для этого можно использовать расширение параметров bash:
for file in * ; do
replace_all=${file//./_}
newname=${replace_all%_*}.${replace_all##*_}
mv "$file" "$newname"
done
//./_
означаетзаменить все точки на подчеркивания%_*
означаетудалить все после последнего подчеркивания##*_
означаетудалить все до последнего подчеркивания
Или вы можете сначала сохранить расширение, затем удалить его, заменить все точки на подчеркивания и добавить расширение обратно. Оставлено в качестве упражнения для читателя.
решение2
Утилита perl
на основе - rename
может использовать любые perl
операторы для переименования файлов, а не только s///
оператор поиска и замены или y//
оператор перевода (просто убедитесь, что вы указали $_
то, во что хотите переименовать файл).
От man rename
:
"rename" переименовывает предоставленные имена файлов в соответствии с правилом, указанным в качестве первого аргумента. Аргумент perlexpr — это выражение Perl, которое, как ожидается, изменит
$_
строку в Perl по крайней мере для некоторых из указанных имен файлов. Если заданное имя файла не изменено выражением, оно не будет переименовано. Если в командной строке не указаны имена файлов, имена файлов будут считываться через стандартный ввод.
Например:
rename 'my($b,$e) = m/^(.*)\.([^.]+)$/; $b =~ s/\./_/g; $_="$b.$e"' files
Это разделяет имена файлов на базовое имя ($b) и расширение ($e). Затем в $b все точки ( .
) заменяются подчеркиваниями. Наконец, $_
устанавливается значение "$b.$e"
.
Вывод (с -v
опцией verbose):
$ touch top_axi_256_wrapper_05.02.01.14.00_sample06.tgz \
top_axi_128_wrapper_05.02.01.14.00_sample06.tgz \
a72_a_0.0.0_0.00.04_ac_dc.tgz
$ rename -v 'my($b,$e) = m/^(.*)\.([^.]+)$/; $b =~ s/\./_/g; $_="$b.$e"' *
a72_a_0.0.0_0.00.04_ac_dc.tgz renamed as a72_a_0_0_0_0_00_04_ac_dc.tgz
top_axi_128_wrapper_05.02.01.14.00_sample06.tgz renamed as top_axi_128_wrapper_05_02_01_14_00_sample06.tgz
top_axi_256_wrapper_05.02.01.14.00_sample06.tgz renamed as top_axi_256_wrapper_05_02_01_14_00_sample06.tgz
Кстати, используйте -n
при проверке своих rename
утверждений. Еще от man rename
:
-н, -ноно
Никаких действий: вывести имена файлов, которые необходимо переименовать, но не переименовывать их.
perl rename
доступен в виде пакетов для большинства дистрибутивов (например, rename
пакет в Debian) или изhttps://metacpan.org/release/File-Rename