如何为文件名添加转义字符以适配Shell命令执行?
解决含特殊字符的文件名导致ffmpeg命令执行失败的问题
你遇到的问题是因为带空格、括号这类特殊字符的文件名直接拼进shell命令后,会被shell当成语法分隔符解析,导致ffmpeg无法正确识别文件路径。这里有两种可靠的解决办法,优先推荐第一种:
方案1:使用参数列表传递命令(最优)
不要用shell=True,而是把命令拆成参数列表传给subprocess.Popen,这样subprocess会自动处理文件名里的特殊字符,不需要手动转义,这也是Python官方推荐的方式。
修改后的核心代码如下:
for filename in os.listdir(directory): if filename.endswith(tuple(VIDEO_EXTENSIONS)): print(f'PROCESSING: {filename}...') abs_file_path = os.path.join(directory, filename) # 用参数列表替代字符串拼接,默认shell=False proc = subprocess.Popen( ['./ffmpeg', '-v', 'error', '-i', abs_file_path, '-f', 'null', '-'], stdout=subprocess.PIPE, stderr=subprocess.PIPE # 直接捕获stderr,无需写2>&1 ) # ffmpeg的错误信息输出到stderr,所以取communicate的第二个返回值 output = proc.communicate()[1] row = '' if not output: print("\033[92m{0}\033[00m".format("HEALTHY -> {}".format(filename)), end='\n') row = [filename, 0] else: print("\033[31m{0}\033[00m".format("CORRUPTED -> {}".format(filename)), end='\n') row = [filename, 1] results_file_writer.writerow(row) results_file.flush() results_file.flush() results_file.close()
说明:
- 将命令的每个部分拆分为列表元素,文件路径直接作为独立元素传入,subprocess会确保它被ffmpeg完整识别。
- 无需依赖shell解析命令,从根源避免了特殊字符的解析冲突。
方案2:手动转义文件名(备选)
如果你一定要保留shell=True,可以用Python的shlex.quote()函数来自动转义shell敏感字符,它会给文件名添加合适的引号或转义符,确保shell将其视为一个整体路径。
示例代码:
import shlex # ... 其他代码不变 ... abs_file_path = os.path.join(directory, filename) # 自动转义特殊字符 escaped_path = shlex.quote(abs_file_path) # 拼入命令字符串 proc = subprocess.Popen(f'./ffmpeg -v error -i {escaped_path} -f null - 2>&1', shell=True, stdout=subprocess.PIPE) output = proc.communicate()[0] # ... 后续代码不变 ...
这个函数会把Movie Name (1080p)转成'Movie Name (1080p)'(单引号包裹),shell会将单引号内的内容当作整体处理,不会解析其中的空格和括号。
内容的提问来源于stack exchange,提问作者nhershy
相关产品推荐
相关产品推荐

