Python 在subprocess.Popen中使用通配符
我已经找到了一些解决通过Popen传递通配符问题的答案,但我似乎无法让这些解决方案在我的特定情况下发挥作用 我有一个项目,按下按钮时将合并音频和视频文件,我需要使用subprocess.Popen执行我想要的命令:Python 在subprocess.Popen中使用通配符,python,raspberry-pi,subprocess,wildcard,Python,Raspberry Pi,Subprocess,Wildcard,我已经找到了一些解决通过Popen传递通配符问题的答案,但我似乎无法让这些解决方案在我的特定情况下发挥作用 我有一个项目,按下按钮时将合并音频和视频文件,我需要使用subprocess.Popen执行我想要的命令: mergeFile = "ffmpeg -i /home/pi/Video/* -i /home/pi/Audio/test.wav -acodec copy -vcodec copymap 0:v -map 1:a /home/pi/Test/output.mkv" proc= s
mergeFile = "ffmpeg -i /home/pi/Video/* -i /home/pi/Audio/test.wav -acodec copy -vcodec copymap 0:v -map 1:a /home/pi/Test/output.mkv"
proc= subprocess.Popen(shlex.split(mergeFiles), shell=True)
我基本上想把我的视频文件夹中的任何文件(我的项目从相机下载视频,每次保存新视频时文件名都会更改)合并到单独的“音频”文件夹中的音频,然后将该文件保存到另一个文件夹中
我试着将shell设置为true,但没有任何效果
我也不知道glob模块在这种情况下会如何帮助我。这里的问题是
shlex.split()
。当与shell=True
结合使用时,这意味着只有字符串ffmpeg
被视为脚本,并且命令行的其他组件作为参数传递给该脚本(它从不查看/读取)
更好的做法是仍然使用
shell=True
(如果您实际正在参数化目录名和文件名),可能是:
mergeFile=[
'ffmpeg -i "$1"/* -i "$2" -acodec copy -vcodec copymap 0:v -map 1:a "$3"',
'_', # placeholder for $0
"/home/pi/Video", # directory for $1 -- can use a variable here
"/home/pi/Audio/test.wav",
"/home/pi/Test/output.mkv",
]
subprocess.Popen(mergeFile, shell=True)
…在这种情况下,脚本本身是常量(不能通过文件名或其他参数注入的值来更改其含义),但可以提供带外数据
比这更好的是完全停止使用
shell=True
。考虑:
import subprocess, glob
mergeFile=[
'ffmpeg', '-i',
] + (glob.glob('/home/pi/Video/*') or ['/home/pi/Video/*']) + [
'-i', '/home/pi/Audio/test.wav',
'-acodec', 'copy',
'-vcodec', 'copymap', '0:v',
'-map', '1:a1',
'/home/pi/Test/output.mkv'
]
subprocess.Popen(mergefile)
存在
或['/home/pi/Video/*']
时,如果不存在与glob匹配的文件,则会产生与shell相同的错误消息。显然,在这种情况下也可以中止。取出shlex.split()
。只需传递字符串本身即可。将shlex.split()
与subprocess.Popen()
结合使用是一个常见的习惯用法(使用shell=False
)——这是一个非常不幸的习惯用法,IMHO。使用shell=False
的全部目的是允许传递一个明确的、明确的参数列表(正好包含您想要的文件名和其他参数)——当您开始将参数列表形成一个字符串,然后让库解析该字符串时,你突然增加了模糊性,你可以选择没有……而且,很清楚,shell=True
是模糊的,容易出现安全漏洞,或者是一个坏主意。考虑一下,如果不是硬编码一个文件名在你的代码> MiGeFrase字符串中,你就从上传目录中获得了<代码>操作系统.ListDIR()/<代码>——除非你小心地创建了那个字符串,一个用<代码>触摸$$(RM -Rf)\ $(RM -Rf)创建的文件。\“.wav可能会产生非常不幸的副作用。shlex.split()
是抵御shell注入攻击的第一道防线,我认为这就是为什么它可以优于shell=True
。它不能捕获所有内容,最终可能会将shell元字符作为参数传递给混淆的结果,但它仍然优于替代方法。@tdelaney,“替代方法”(至少在最佳可用替代方法的意义上)不是shell=True
——替代方法是传递一个显式argv数组shell=False
withshlex.split()
确实将您从$(…)
中保存,但对于名为foo的文件--execute trigger command=…
没有帮助;将所有参数传递到带外(即使使用shell=True
,就像[“脚本在此处使用“$1”和“$2”,“'''u',参数1,参数2]
)一样)是正确的;任何不足之处都是一种折衷。(当然,--execute trigger command=
有点做作,但对于我们当前的ffmpeg,有许多选项/命令可用于使用当前用户的代理凭据SSH到资源;从本地网络检索内容;或以其他方式制造麻烦——请参阅)。
import subprocess, glob
mergeFile=[
'ffmpeg', '-i',
] + (glob.glob('/home/pi/Video/*') or ['/home/pi/Video/*']) + [
'-i', '/home/pi/Audio/test.wav',
'-acodec', 'copy',
'-vcodec', 'copymap', '0:v',
'-map', '1:a1',
'/home/pi/Test/output.mkv'
]
subprocess.Popen(mergefile)