循环浏览具有特定扩展名的所有文件


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

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

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

在情况#1中,break是好的,因为$i没有其他值,breakcontinue将是等效的(尽管我发现break更明确;您正在退出循环,而不仅仅是被动地等待循环退出)。

在第2种情况下,您仍然需要对任何可能的匹配进行任何必要的过滤。因此,breakcontinue的选择不如您应用于$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 matchingpattern matching

功能新测试[[旧测试[示例模式匹配=(或==)(不可用)[[$name=a*]]|| echo"名称不以'a':$name开头"正则表达式=~(不可用)[[$(date)=~^Fri\…\13]]&&echo"今天是13号星期五!"匹配

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

编辑:任何关于如何将答案中的数据格式化为表格的建议都会很有帮助!

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

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

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

相关内容

  • 没有找到相关文章