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
选项简单地忽略失败的匹配而不进入循环的主体。
shopt -s nullglob
for i in *.java; do
...
done
评论中关于break
与continue
讨论的更多细节。我认为无论使用break
还是continue
都有点超出范围,因为第一个循环试图区分两种情况:
*.java
没有匹配项,因此被视为文本*.java
至少有一个匹配项,该匹配项可能包含一个名为*.java
的条目
在情况#1中,break
是好的,因为$i
没有其他值,break
和continue
将是等效的(尽管我发现break
更明确;您正在退出循环,而不仅仅是被动地等待循环退出)。
在第2种情况下,您仍然需要对任何可能的匹配进行任何必要的过滤。因此,break
或continue
的选择不如您应用于$i
的哪个测试(-f
、-d
、-e
等)相关,哪个IMO是确定您是否进入循环的错误方法;错误地";首先。
也就是说,在情况#1中,我根本不想检查$i
的值,在情况#2中,您对该值的处理更多地与每个文件的业务逻辑有关,而不是首先选择要处理的文件的逻辑。我更愿意把这个逻辑留给个人用户,而不是在问题中表达一个或另一个选择。
顺便说一句,zsh
提供了一种在glob本身中进行这种过滤的方法。您可以使用仅匹配以.java
结尾的常规文件(并禁用将不匹配的模式视为错误而非文本的默认行为)
for f in *.java(.N); do
...
done
通过以上操作,您可以保证如果到达循环的主体,则$f
将扩展为常规文件的名称。.
使*.java
仅与常规文件匹配,而N
使失败的匹配扩展为零,而不是产生错误。
还有其他类似的glob限定符,用于对文件名展开进行各种过滤。(我开玩笑说zsh
的glob扩展完全取代了使用find
的需要。)
递归添加子文件夹,
for i in `find . -name "*.java" -type f`; do
echo "$i"
done
循环所有以:.img
、.bin
、.txt
后缀结尾的文件,并打印文件名:
for i in *.img *.bin *.txt;
do
echo "$i"
done
或者以递归方式(也可以在所有子目录中找到):
for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
echo "$i"
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
正如@chepner在他的评论中所说,您正在将$i与固定字符串进行比较。
要扩展和纠正这种情况,您应该使用[[]]和regex运算符=~
例如:
for i in $(ls);do
if [[ $i =~ .*.java$ ]];then
echo "I want to do something with the file $i"
fi
done
=~右边的正则表达式是根据左手运算符的值进行测试的,不应该被引用,(引用不会出错,但会与固定字符串进行比较,因此很可能会失败">
但@chepner的答案是,使用glob是一种更有效的机制。
关于循环文件的正确方式,我同意其他答案。然而,OP问道:
上面的代码不起作用,你知道为什么吗?
是的!
一篇优秀的文章test和[[之间的区别是什么?]详细解释了在其他区别中,不能在test
命令([
的缩写)中使用expression matching
或pattern matching
功能新测试[[旧测试[示例模式匹配=(或==)(不可用)[[$name=a*]]|| echo"名称不以'a':$name开头"正则表达式=~(不可用)[[$(date)=~^Fri\…\13]]&&echo"今天是13号星期五!"匹配
所以这就是脚本失败的原因。如果OP对[[
语法的答案感兴趣(它的缺点是在[
命令这样多的平台上不受支持),我很乐意编辑我的答案以包含它。
编辑:任何关于如何将答案中的数据格式化为表格的建议都会很有帮助!
我发现这个解决方案非常方便。它使用find
:中的-or
选项
find . -name *.tex -or -name "*.png" -or -name "*.pdf"
它将查找扩展名为tex
、png
和pdf
的文件。