"find / -name 'testmkv-27311.mkv' -exec bash -c 'ffmpeg -i testmkv-27311.mkv -vcodec copy -acodec copy -codec:v libx264 -profile:v high -preset slow -b:v 500k -maxrate 500k -bufsize 1000k -vf scale=-1:480 -threads 0 -codec:a libfdk_aac -b:a 128k {}testmkv-27311.mp4' \;"
是我传递的命令,它给出了错误的查找...已经有一些关于它的答案但它们没有说清楚......请帮我执行这个命令......
答案 0 :(得分:2)
在shell中的未加引号的上下文中,\;
阻止将;
解析为命令分隔符。但是,在没有shell=True
的情况下从Python调用带有参数列表的命令时, 没有shell来解释和删除该反斜杠,并且额外的引用使行为等同于传递{{1}在shell中 - 意味着传递给'\;'
的参数不是它期望的确切字符串find
,并且您得到语法错误。
但是,原始代码在其他方面也是不正确的(在影响安全的方面!);应使用以下解决方案之一。
;
就个人而言,如果你愿意对输出名称(即find
)稍微有点灵活,我会写得更像以下内容:
testmkv-27311.mkv.avi
值得注意的是:
subprocess.call([
'find', '/',
'-name', 'testmkv-27311.mkv',
'-exec',
'ffmpeg',
'-i', '{}',
'-vcodec', 'copy',
'-acodec', 'copy',
'-codec:v', 'libx264',
'-profile:v', 'high',
'-preset', 'slow',
'-b:v', '500k',
'-maxrate', '500k',
'-bufsize', '1000k',
'-vf', 'scale=-1:480',
'-threads', '0',
'-codec:a', 'libfdk_aac',
'-b:a', '128k',
'{}.mp4',
';',
])
支持find -exec
作为子字符串(而不是完整的参数)。因此,这个答案(就像问题中的代码一样)并不像人们希望的那样便携。也就是说,根本没有令人信服的理由使用{}
,当Python标准库可以对你进行搜索时,和可以很容易地更新自己命名:
find
另一种安全地执行此操作的方法(不让def convert(filename_in, filename_out):
subprocess.call([
'ffmpeg',
'-i', filename_in,
'-vcodec', 'copy',
'-acodec', 'copy',
'-codec:v', 'libx264',
'-profile:v', 'high',
'-preset', 'slow',
'-b:v', '500k',
'-maxrate', '500k',
'-bufsize', '1000k',
'-vf', 'scale=-1:480',
'-threads', '0',
'-codec:a', 'libfdk_aac',
'-b:a', '128k',
filename_out,
])
target = 'testmkv-27311.mkv'
for root, dir, files in os.walk('/'):
if target in files:
filename_in = os.path.join(dir, target)
filename_out = filename_in[:-3]+'.mp4'
convert(filename_in, filename_out)
修改或生成名称中的代码,允许这些名称被shell解析为代码),您可以拥有你的bash脚本迭代它的参数:
find
在这种情况下,bash_script=r'''
for filename; do
ffmpeg -i "$filename" \
-vcodec copy \
-acodec copy \
-codec:v libx264 \
-profile:v high \
-preset slow \
-b:v 500k \
-maxrate 500k \
-bufsize 1000k \
-vf scale=-1:480 \
-threads 0 \
-codec:a libfdk_aac \
-b:a 128k \
"${filename%.mkv}.mp4}"
done
'''
subprocess.call([
'find', '/',
'-name', 'testmkv-27311.mkv',
'-exec', 'bash', '-c', bash_script, '_',
'{}', '+'])
是脚本中_
的占位符;后续参数($0
找到的文件名)在find
,$1
等中传递; $2
(默认为for filename; do
)会迭代它们。
使用for filename in "$@"; do
传递尽可能多的文件名到每个命令,而不是每个文件名调用一次命令;这减少了调用的shell数量,从而提高了性能。