Я хочу переименовать все файлы в каталоге с *.ts на *.mkv [дубликат]

Встроенный gR (как предлагает @SatoKatsura) отлично подходит, если длина старого и нового одинакова. Однако в общем случае это не работает, и необходимо использовать другой подход. Мне это нужно так часто, что я написал плагин для упрощения и обеспечения максимальной скорости: ReplaceWithRegister .

Этот плагин предлагает команду «два в одном» gr , которая заменяет текст, охватываемый объектом {motion} / text, всей строкой (строками) или текущим выделением, содержимым регистра; старый текст удаляется в регистр черной дыры, т.е. Он прозрачно обрабатывает многие угловые случаи и позволяет быстро повторять через стандарт . команда. Если вам это не нравится, на его странице есть ссылки на альтернативные варианты.

2
28.01.2019, 03:32
5 ответов

Самым простым решением было бы попросить вас изменить назначение на:

new_name=$( echo ${file} | sed -e 's|.ts|.mkv|' )

Но лучшим решением было бы сделать:

new_name="${file%.ts}.mkv"
3
27.01.2020, 21:52
#!/bin/sh
for file in "${1}"/*.ts; do
   mv "${file}" "$(basename "${file}").mkv"
done
-1
27.01.2020, 21:52

rename это то, что вы ищете:

rename '.ts' '.mkv' "${1}/*.ts"
0
27.01.2020, 21:52

Используя $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, если хотите дополнительно сопоставить скрытые имена файлов.

0
27.01.2020, 21:52
find. -maxdepth 1 -type f -name '*.ts' -exec rename.ts.mkv {} "+"

Запустите это в каталоге, содержащем файлы .ts.

2
27.01.2020, 21:52

Теги

Похожие вопросы