循环遍历所有具有特定扩展名的文件

for i in $(ls);do if [ $i = '*.java' ];then echo "I do something with the file $i" fi done 

我想循环通过当前文件夹中的每个文件,并检查它是否符合特定的扩展名。 上面的代码不起作用,你知道为什么吗?

没有花哨的技巧需要:

 for i in *.java; do [ -f "$i" ] || break ... done 

警卫确保如果没有匹配的文件,循环将退出而不处理不存在的文件名*.java 。 在bash (或支持类似的shell)中,可以使用nullglob选项来简单地忽略失败的匹配,而不是input循环的主体。

 shopt -s nullglob for i in *.java; do ... done 

正确的答案是@ chepner的

 EXT=java for i in *.${EXT}; do ... done 

然而,这里有一个小技巧来检查一个文件名是否有给定的扩展名:

 EXT=java for i in *; do if [ "${i}" != "${i%.${EXT}}" ];then echo "I do something with the file $i" fi done 

recursion添加子文件夹,

 for i in `find . -name "*.java" -type f`; do echo $i done 

正如@chepner在他的评论中所说,你正在比较$ i到一个固定的string。

为了扩大和纠正这种情况,您应该使用[[]]和正则expression式运算符=〜

例如:

 for i in $(ls);do if [[ $i =~ .*\.java$ ]];then echo "I want to do something with the file $i" fi done 

正确的=〜的正则expression式是针对左侧操作符的值进行testing的,不应该引用,(引用不会错误,但会与固定string进行比较,因此很可能会失败“

但是@chepner的使用glob的回答是一个更有效的机制。

我同意关于正确的方式循环通过文件的其他答案。 不过,OP问:

上面的代码不起作用,你知道为什么吗?

是!

一篇优秀的文章testing之间有什么区别,[和[[?]详细解释了除了其他差异,你不能使用expression matchingpattern matching内的test命令(这是[ ]的简写]


function新testing[[旧testing[例子

模式匹配=(或==)(不可用)[[$ name = a *]] || 回声“名称不以”a“开头:$ name”

正则expression式=〜(不可用)[[$(date)=〜^ Fri \ ... \ 13]] && echo“这是十三号星期五!
匹配

所以这就是你的脚本失败的原因。 如果OP感兴趣的是[[语法(其缺点是没有像[命令]那样多的平台上的支持),我很乐意编辑我的答案,包括它。

编辑:如何格式化答案中的数据作为表的任何protip将有所帮助!