PHP调用Shell循环与find命令仅获取文件名出错求助
解决find命令报错"paths must precede expression"的问题
我来帮你搞定这个find命令的问题!你遇到的这个报错,本质是find的参数顺序或者表达式格式不对——find要求先指定搜索路径,再写过滤条件/执行逻辑,而且如果表达式里有特殊字符没处理,也会让它误解你的指令。
先直接给你能实现需求的正确命令,再拆解解释:
find . -type f -exec sh -c ' # 批量接收find找到的文件 for file do # 提取文件名(不含扩展名) # ${file##*/} 先去掉文件的路径部分,只留文件名 filename=${file##*/} # ${filename%.*} 去掉文件名的最后一个.及后面的扩展名 base_name=${filename%.*} # 组合成你要的输出格式 output_name="Frame55Grab${base_name}.bmp" # 这里可以替换成你实际要执行的操作,比如复制、转换文件 echo "原文件:$file → 输出文件:$output_name" # 示例:如果是要复制文件,用下面的命令 # cp "$file" "$output_name" done ' sh {} +
为什么你的命令会报错?
大概率是这两个原因之一:
- 参数顺序错误:你可能把执行逻辑写在了路径前面,比如直接写
find -exec ...而没先指定搜索路径(比如.代表当前目录),find就会把后面的内容当成路径,导致混乱。 - 特殊字符未处理:你用到的
%d在find的-exec语法里有特殊含义(比如%p代表文件完整路径),直接写Frame55Grab%d.bmp会让find误解这是表达式的一部分,而非普通字符串。
命令拆解说明
find . -type f:从当前目录(.)开始,搜索所有普通文件(排除目录、链接等)-exec sh -c '...' sh {} +:把find找到的文件批量传给shell脚本处理,{} +表示把所有匹配的文件一次性传给脚本,比逐个处理的{} \;效率高很多filename=${file##*/}:剥离文件的路径部分,只保留纯文件名(比如./docs/test.txt变成test.txt)base_name=${filename%.*}:去掉文件名的扩展名(比如test.txt变成test)- 最后把
base_name和Frame55Grab、.bmp组合成目标文件名
如果只需要处理特定扩展名的文件(比如只处理.png),可以加个过滤条件:
find . -type f -name "*.png" -exec sh -c ' for file do filename=${file##*/} base_name=${filename%.png} output_name="Frame55Grab${base_name}.bmp" echo "原文件:$file → 输出文件:$output_name" done ' sh {} +
内容的提问来源于stack exchange,提问作者Peter Friedlander
相关产品推荐
相关产品推荐

