查找:使用子进程时缺少"-exec"的参数 [英] find: missing argument to `-exec' when using subprocess

查看:66
本文介绍了查找:使用子进程时缺少"-exec"的参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

"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' \;"

是我正在传递的命令,它给find带来了错误...已经有一些答案了,但是他们没有弄清楚...请帮助我执行此命令...

is the command i am passing and it gives error with find... there are some answers already about it but they are not making it clear... please help me execute this command...

推荐答案

立即发行:Shell报价与Python报价

在shell中未加引号的上下文中, \; 防止; 被解析为命令分隔符.但是,当从Python中调用不带 shell = True 的带有参数列表的命令时,没有 没有解释和删除该反斜杠的外壳,并且额外的引号使行为等同于在外壳中传递'\;'-意味着传递给 find 的参数不是确切的字符串; ,这是您所期望的,并且您得到语法错误.

Immediate Issue: Shell Quoting vs Python Quoting

In an unquoted context in shell, \; prevents ; from being parsed as a command separator. When invoking a command with an argument list from Python without shell=True, however, there is no shell to interpret and remove that backslash, and that extra quoting makes behavior equivalent to passing '\;' in shell -- meaning the argument passed to find isn't the exact string ; it's expecting, and that you get a syntax error.

但是,在其他方面,原始代码也不正确(以影响安全性的方式!);应该使用以下解决方案之一.

就个人而言,如果您愿意在输出名称(例如 testmkv-27311.mkv.avi )上稍加灵活,我会像下面这样写:

Personally, if you're willing to be a little flexible on the output names (ie. testmkv-27311.mkv.avi), I would write this more like the following:

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',
      ';',
])

值得注意的是:

  • 我们调用shell,从而避免了shell注入式的安全漏洞.
  • 报价完全是用Python语法完成的,没有使用或不需要嵌套的shell报价.
  • POSIX不需要 find -exec 来支持 {} 作为子字符串(而不是完整的参数).因此,此答案(如问题中的代码)不如希望的那样具有可移植性.
  • We are not invoking a shell, and thus avoiding shell-injection-style security vulnerabilities.
  • Quoting is all done purely with Python syntax -- no nested shell quoting is used or required.
  • POSIX does not require find -exec to support {} as a substring (rather than a complete argument). As such, this answer is (like the code in the question) not as portable as might be hoped.

也就是说,根本没有令人信服的理由使用 find ,当Python标准库可以为您进行搜索时,会变得很容易自行更新名称:

That said, there isn't really a compelling reason to use find at all, when the Python standard library can do searches for you, and will make it easy to update the names yourself:

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)


另一种安全方法:在参数上迭代的硬编码脚本

作为安全地执行此操作的另一种方法( find 来从名称中修改或生成代码,这使得外壳程序可以将这些名称解析为代码),您可以让bash脚本遍历其参数:


Alternate Safe Approach: Hardcoded Script Iterating Over Arguments

As yet another approach to doing this securely (not having find modify or generate code from names, which allows those names to be parsed as code by the shell), you could have your bash script iterate over its arguments:

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 等中传递;和表示文件名;做(对于"$ @"中的文件名,默认为;做)将遍历它们.

In this case, the _ is the placeholder for $0 in the script; subsequent arguments (the filenames found by find) are passed in $1, $2, etc; and for filename; do (which defaults to for filename in "$@"; do) will iterate over them.

使用 -exec ... {} + 将尽可能多的文件名传递给每个命令,而不是每个文件名调用一次命令.这样可以减少调用的shell数量,从而提高性能.

Using -exec ... {} + passes as many as filenames as possible to each command, rather than invoking the command once per filename; this reduces the number of shells invoked, and thus enhances performance.

这篇关于查找:使用子进程时缺少"-exec"的参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆