小编典典

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

all

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

我想遍历当前文件夹中的每个文件并检查它是否与特定扩展名匹配。上面的代码不起作用,你知道为什么吗?


阅读 277

收藏
2022-09-02

共1个答案

小编典典

不需要花哨的技巧:

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

守卫确保如果没有匹配的文件,循环将退出而不尝试处理不存在的文件名*.java

bash(或支持类似内容的 shell)中,您可以使用该nullglob选项来简单地忽略失败的匹配并且不进入循环体。

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

break评论中有关-vs-continue讨论的更多细节。break无论您使用or
,我都认为它有点超出范围continue,因为第一个循环试图做的是区分两种情况:

  1. *.java没有匹配项,因此被视为文字文本。
  2. *.java至少有一个匹配项,并且该匹配项可能包含一个名为*.java.

在 #1
的情况下,break很好,因为没有其他$i即将到来的值,break并且continue将是等价的(尽管我发现break更明确;您正在退出循环,而不仅仅是被动地等待循环退出)。

在情况 #2 中,您仍然需要对任何可能的匹配项进行必要的过滤。因此,选择breakor与您应用的 测试 (,
,等)continue的相关性较低,IMO 是确定您是否首先“错误地”进入循环的错误方法。 __-f``-d``-e``$i

$i 也就是说,我根本 不想在案例#1 中检查 的值,而在案例#2 中,你对值的处理更多地与每个文件的业务逻辑有关,而不是首先 选择
要处理的文件的逻辑。我宁愿把这个逻辑留给个人用户,而不是在问题中表达一个或另一个选择。


顺便说一句,zsh提供了一种在 glob 本身中进行这种过滤的方法。您可以
.java匹配以(并禁用将不匹配模式视为错误而不是文本文本的默认行为)结尾的常规文件

for f in *.java(.N); do
  ...
done

有了上面的内容,你可以 保证
如果你到达循环的主体,然后$f扩展为一个常规文件的名称。.make*.java只匹配常规文件,并且导致失败的N匹配扩展为空而不是产生错误。

还有其他此类 glob 限定符 用于对文件名扩展进行各种过滤。(我喜欢开玩笑说zsh‘ 的 glob 扩展完全取代了使用的需要find。)

2022-09-02