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。
*.java
在bash(或支持类似内容的 shell)中,您可以使用该nullglob选项来简单地忽略失败的匹配并且不进入循环体。
bash
nullglob
shopt -s nullglob for i in *.java; do ... done
break评论中有关-vs-continue讨论的更多细节。break无论您使用or ,我都认为它有点超出范围continue,因为第一个循环试图做的是区分两种情况:
break
continue
在 #1 的情况下,break很好,因为没有其他$i即将到来的值,break并且continue将是等价的(尽管我发现break更明确;您正在退出循环,而不仅仅是被动地等待循环退出)。
$i
在情况 #2 中,您仍然需要对任何可能的匹配项进行必要的过滤。因此,选择breakor与您应用的 测试 (, ,等)continue的相关性较低,IMO 是确定您是否首先“错误地”进入循环的错误方法。 __-f``-d``-e``$i
-f``-d``-e``$i
$i 也就是说,我根本 不想在案例#1 中检查 的值,而在案例#2 中,你对值的处理更多地与每个文件的业务逻辑有关,而不是首先 选择 要处理的文件的逻辑。我宁愿把这个逻辑留给个人用户,而不是在问题中表达一个或另一个选择。
顺便说一句,zsh提供了一种在 glob 本身中进行这种过滤的方法。您可以 仅.java匹配以(并禁用将不匹配模式视为错误而不是文本文本的默认行为)结尾的常规文件
zsh
.java
for f in *.java(.N); do ... done
有了上面的内容,你可以 保证 如果你到达循环的主体,然后$f扩展为一个常规文件的名称。.make*.java只匹配常规文件,并且导致失败的N匹配扩展为空而不是产生错误。
$f
.
N
还有其他此类 glob 限定符 用于对文件名扩展进行各种过滤。(我喜欢开玩笑说zsh‘ 的 glob 扩展完全取代了使用的需要find。)
find