如何在bash的find -exec命令中替换{}中的字符串?
在bash的find命令中替换{}里的字符串(将.in转为.out)
这个需求我经常碰到,给你几个靠谱的解决方案,都是bash环境下直接能用的,还能兼容带空格或特殊字符的文件名:
方法一:用-exec bash -c直接处理(最推荐)
这是最安全也最直观的方式,借助bash的参数扩展功能来替换后缀:
find . -name "*.in" -exec bash -c 'python somescript.py "$0" "${0%.in}.out"' {} \;
原理说明:
bash -c '...' {}:让bash执行后面的命令字符串,把find匹配到的文件名(也就是{})作为$0传递给这个bash子进程${0%.in}:bash的参数扩展语法,意思是去掉$0(原文件名)末尾的.in后缀- 再拼接上
.out,就得到了对应的目标文件名
方法二:配合xargs使用(适合批量处理)
如果文件数量很多,用xargs可以减少创建子进程的次数,效率更高:
find . -name "*.in" -print0 | xargs -0 -I {} bash -c 'python somescript.py "$0" "${0%.in}.out"' {}
补充说明:
-print0和-0是配对使用的,用来处理包含空格、换行符或者特殊字符的文件名,避免出现解析错误-I {}指定用{}作为xargs的占位符,把每个文件名传递给后面的bash命令
方法三:用sed生成命令再执行(慎用)
这种方式是通过sed把每个.in文件名转换成完整的命令,再交给bash执行,但要注意文件名里不能有特殊字符(比如&、*):
find . -name "*.in" | sed 's/\(.*\)\.in/python somescript.py "\1.in" "\1.out"/' | bash
原理:
- sed的
s/\(.*\)\.in/.../把每个文件名分成两部分,\1代表.in前面的部分,然后拼接成目标命令
不管用哪种方法,记得给文件名加上双引号,防止因为空格或特殊字符导致命令执行出错哦~
内容的提问来源于stack exchange,提问作者jul
相关产品推荐
相关产品推荐

