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

时间:2013-01-24 15:36:39

标签: bash file glob

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

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

7 个答案:

答案 0 :(得分:165)

不需要花哨的技巧:

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

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

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

答案 1 :(得分:13)

正确答案是@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

答案 2 :(得分:9)

递归添加子文件夹,

for i in `find . -name "*.java" -type f`; do
    echo "$i"
done

答案 3 :(得分:3)

浏览所有以.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

答案 4 :(得分:2)

正如@chepner在评论中所说,你将$ i与固定字符串进行比较。

要扩展和纠正这种情况,你应该使用[[]]和正则表达式运算符=〜

例如:

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

=〜右边的正则表达式是针对左手操作符的值进行测试的,不应该引用,(引用不会出错但会与固定字符串进行比较,因此很可能会失败“

但@chepner上面使用glob的答案是一种更有效的机制。

答案 5 :(得分:2)

我同意关于循环文件的正确方法的其他答案。然而,OP问:

  

上面的代码不起作用,你知道为什么吗?

是!

优秀文章 What is the difference between test, [ and [[ ?] 详细解释了除了其他差异之外,您无法在expression matching命令中使用pattern matchingtest(这是{{1}的简写})


Feature            new test [[    old test [           Example

Pattern matching    = (or ==)    (not available)    [[ $name = a* ]] || echo "name does not start with an 'a': $name"

Regular Expression     =~        (not available)    [[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "It's Friday the 13th!"
matching

所以这就是你的脚本失败的原因。如果OP对[语法的答案感兴趣(其缺点是在[[命令的平台上不受支持),我很乐意编辑我的答案以包含它

编辑:如何将答案中的数据格式化为表格的任何说明都会有所帮助!

答案 6 :(得分:2)

我发现此解决方案非常方便。它使用-or中的find选项:

find . -name \*.tex -or -name "*.png" -or -name "*.pdf"

它将找到扩展名为texpngpdf的文件。