MacOS下find传递路径被截断导致FFmpeg转换失败的问题
问题描述
使用MacOS 13.0.1,尝试通过find命令遍历带空格和特殊字符的.mov文件,借助FFmpeg转换为MP4格式,编写了如下脚本:
function convert_to_mp4_then_rm() { while IFS= read -r -d '' file do ffmpeg -i "$file" "${file%.mov}.mp4" done < <(find /Users/f.weber/Downloads -type f -name "*.mov" -print0) }
脚本可运行,但出现路径截断问题:FFmpeg接收的部分路径被截断,例如完整路径为/Users/f.weber/Downloads/23-09-26 08-56-50-2539.mov,FFmpeg实际收到的却是/Downloads/23-09-26 08-56-50-2539.mov,提示文件不存在;长路径时截断更明显,甚至出现在单词中间。
问题原因
核心原因是shell对路径中的特殊字符(如$、!、反斜杠等)进行了意外解析,导致路径被篡改或截断:
- 虽然脚本用了
-print0和read -d ''来处理含空格的文件名,但如果文件名包含shell特殊字符(比如路径里的$weber会被bash/zsh解析为变量,若变量不存在则被替换为空),即使加了双引号"$file",shell仍会对这些字符进行扩展,破坏完整路径。 - MacOS默认shell是zsh,其部分扩展规则与bash不同,可能加剧这种解析异常。
解决方法
改用find -exec sh -c的方式直接处理文件,避免路径经过shell的额外解析,确保完整路径传递给FFmpeg:
function convert_to_mp4_then_rm() { find /Users/f.weber/Downloads -type f -name "*.mov" -exec sh -c ' # 遍历传入的所有文件路径参数 for file do # 直接使用参数,无需担心特殊字符解析问题 ffmpeg -i "$file" "${file%.mov}.mp4" done ' sh {} + }
原理说明
find -exec sh -c '...' sh {} +将找到的所有.mov文件路径作为独立参数传递给子shell,子shell的for循环直接读取这些参数,完全避免了路径被父shell解析的问题。- 这种方式比
read循环更可靠,能处理包含任意特殊字符的文件名(包括空格、$、!、换行符等)。
内容的提问来源于stack exchange,提问作者fweber
相关产品推荐
相关产品推荐

