循环遍历所有具有特定扩展名的文件
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 matching
或pattern matching
内的test
命令(这是[
]的简写]
function新testing[[旧testing[例子 模式匹配=(或==)(不可用)[[$ name = a *]] || 回声“名称不以”a“开头:$ name” 正则expression式=〜(不可用)[[$(date)=〜^ Fri \ ... \ 13]] && echo“这是十三号星期五! 匹配
所以这就是你的脚本失败的原因。 如果OP感兴趣的是[[
语法(其缺点是没有像[
命令]那样多的平台上的支持),我很乐意编辑我的答案,包括它。
编辑:如何格式化答案中的数据作为表的任何protip将有所帮助!