仅使用一行 xargs 将 mkv 文件批量转换为 mp4 文件

仅使用一行 xargs 将 mkv 文件批量转换为 mp4 文件

回答使用 for 循环将一批 mp4 转换为 mp3。

我想用一行代码实现类似的功能。经过反复尝试,我找到了以下代码。

ls | grep .mkv | xargs -I {} ffmpeg -i {} -codec copy {}.mp4

但是,输出文件名现在是video.mkv.mp4

我知道我可以简单地再写一行来更改扩展名

ls | grep .mkv.mp4 | sed -e "p;s/\.mkv.mp4$/\.mp4/" | xargs -n2 mv

我想知道是否有一个单一的解决方案。

答案1

没有理由(除了可读性之外)你不能将 shell 循环放在一行代码中 - 并且无论你使用 shell 循环还是xargs -I{}最终都会ffmpeg对每个文件进行一次调用。

无论如何,我都会避免ls | grep- 相反,使用 shell glob。因此作为一行代码(在任何类似 POSIX 的 shell 中,例如 bash):

for f in ./*.mkv; do ffmpeg -i "$f" -codec copy "${f%.mkv}.mp4"; done

如果你决定使用xargs,那么一个选择是切换到 Z-shell,在那里你可以使用glob 限定符生成r每个匹配文件名的 oot,然后根据需要添加输入和输出扩展名。例如:

print -rNC1 ./*.mkv(.N:r) | xargs -r0 -I{} ffmpeg -i {}.mkv -codec copy {}.mp4    # NB zsh not bash

print请注意,我将and -切换为空分隔符,xargs这样您就可以处理任何合法的文件名,包括包含换行符的文件名。

另一个选项是从 切换xargsGNU parallel,它有用于替换字符串的附加选项,包括{.}替换不带扩展名的文件名(相当于循环版本${f%.mkv}或 Z-shell 的:r修饰符):

printf '%s\0' ./*.mkv | parallel -q0 ffmpeg -i {} -codec copy '{.}.mp4'    # any shell, including bash

相关内容