Встроенный gR
(как предлагает @SatoKatsura) отлично подходит, если длина старого и нового одинакова. Однако в общем случае это не работает, и необходимо использовать другой подход.
Мне это нужно так часто, что я написал плагин для упрощения и обеспечения максимальной скорости: ReplaceWithRegister .
Этот плагин предлагает команду «два в одном» gr
, которая заменяет текст, охватываемый объектом {motion} / text, всей строкой (строками) или текущим выделением, содержимым регистра; старый текст удаляется в регистр черной дыры, т.е. Он прозрачно обрабатывает многие угловые случаи и позволяет быстро повторять через стандарт .
команда. Если вам это не нравится, на его странице есть ссылки на альтернативные варианты.
Самым простым решением было бы попросить вас изменить назначение на:
new_name=$( echo ${file} | sed -e 's|.ts|.mkv|' )
Но лучшим решением было бы сделать:
new_name="${file%.ts}.mkv"
#!/bin/sh
for file in "${1}"/*.ts; do
mv "${file}" "$(basename "${file}").mkv"
done
Используя $file
без кавычек в своем коде, вы побуждаете оболочку разбивать свое содержимое на слова на основе значения$IFS
(пробела, табуляции и новой строки по умолчанию ). Затем эти слова будут подвергаться расширению имени файла, если они содержат какие-либо шаблоны подстановки.
Используя echo
, вы, возможно, также расширили бы последовательности обратной косой черты, такие как \n
и \t
, в зависимости от того, какие параметры оболочки были установлены(xpg_echo
).
Ваша первая команда sed
заменит любой символ, за которым следует ts
в имени файла, на .mkv
. Это означает, что имя файла bats.ts
будет изменено на b.mkv.ts
.
Вторая строка в цикле не имеет смысла, так как она берет выходные данные присваивания и передает их sed
по каналу.
Назначение вывода команды переменной выполняется с помощью подстановки команд:
variable=$( some_command )
#!/bin/sh
for name in "$1"/*.ts; do
mv -i "$name" "${name%.ts}.mkv"
done
Это приведет к циклическому просмотру всех файлов с суффиксом имени файла .ts
в каталоге, заданном "$1"
. Каждый файл будет переименован в одно и то же имя, но с удаленным суффиксом имени файла .ts
и вставленным суффиксом .mkv
в конце имени файла.
Подстановка переменной ${variable%pattern}
удалит самый короткий суффикс в $variable
, соответствующий pattern
. Это будет работать, даже если имя файла содержит встроенные символы новой строки.
Используя mv -i
, мы надеемся предотвратить случайную перезапись функцией существующих файлов. Другой способ сделать это - сделать что-то вроде
#!/bin/sh
for name in "$1"/*.ts; do
newname=${name%.ts}.mkv
if [ ! -e "$newname" ]; then
mv "$name" "$newname"
else
printf 'Name "%s" is already taken\n' "$newname" >&2
fi
done
В дополнение к этому тесту вы можете проверить, существует ли $name
для начала. Если шаблон "$1"/.*ts
не соответствует ни одному имени файла, то по умолчанию он останется нераскрытым. Мы можем поймать это с помощью
#!/bin/sh
for name in "$1"/*.ts; do
[ ! -e "$name" ] && break
newname=${name%.ts}.mkv
if [ ! -e "$newname" ]; then
mv "$name" "$newname"
else
printf 'Name "%s" is already taken\n' "$newname" >&2
fi
done
В оболочке bash
вы могли бы использовать shopt -s nullglob
, чтобы несоответствующие шаблоны расширялись до нуля.В bash
вы также можете использовать shopt -s dotglob
, если хотите дополнительно сопоставить скрытые имена файлов.
find. -maxdepth 1 -type f -name '*.ts' -exec rename.ts.mkv {} "+"
Запустите это в каталоге, содержащем файлы .ts
.