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

AR8*_*R89 99 bash glob file

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

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

che*_*ner 181

不需要花哨的技巧:

for i in *.java; do
    [ -f "$i" ] || break
    ...
done
Run Code Online (Sandbox Code Playgroud)

防护确保如果没有匹配的文件,循环将退出而不尝试处理不存在的文件名*.java.在bash(或支持类似的东西的shell)中,您可以使用该nullglob选项简单地忽略失败的匹配而不进入循环体.

shopt -s nullglob
for i in *.java; do
    ...
done
Run Code Online (Sandbox Code Playgroud)

  • 它会实际匹配任何文件.你需要使用`shopt -s nullglob`,这样一个不匹配的模式会扩展为空序列,而不是字面上对待. (7认同)
  • 最简单的方法是添加另一个模式:`for in in*.java*.cpp; do`.如果你在`bash`中使用`shopt -s\textglob`启用扩展模式,你可以在*.@(java | cpp);中编写`for i'.do`. (5认同)
  • @codeforester 是对的,`continue` 是必要的。如果有一个名为 `b.java` 的普通文件和一个名为 `a.java` 的目录,那么循环可以在它到达 `b.java` 之前被 `break` 终止。 (3认同)
  • @chepner对于非专家来说,在答案中指出这一点可能很有用,因为有人可能会复制粘贴并将其发现不起作用。一个完美的例子是有人在执行关键功能之前将所有“ * .jpg”文件转换为“ * .png” (2认同)
  • 而不是 `[ -f "$i" ] || break`,我们需要 `[ -f "$i" ] || 继续`,对吗? (2认同)

uml*_*ute 13

正确答案是@Chepner's

EXT=java
for i in *.${EXT}; do
    ...
done
Run Code Online (Sandbox Code Playgroud)

但是,这是一个检查文件名是否具有给定扩展名的小技巧:

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


lui*_*gil 11

递归添加子文件夹,

for i in `find . -name "*.java" -type f`; do
    echo "$i"
done
Run Code Online (Sandbox Code Playgroud)

  • 如果任何文件的名称中有空格,这将不起作用。 (3认同)
  • @codeforester我确实遇到了这个问题,我已经使用此答案中的方法修复了它:https://askubuntu.com/a/343753/551184 (2认同)

Ben*_*nny 5

循环通过与结尾的所有文件:.img.bin.txt后缀和打印文件名:

for i in *.img *.bin *.txt;
do
  echo "$i"
done
Run Code Online (Sandbox Code Playgroud)

或以递归的方式(也在所有子目录中找到):

for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
  echo "$i"
done
Run Code Online (Sandbox Code Playgroud)