for i in $(ls);do
if [ $i = '*.java' ];then
echo "I do something with the file $i"
fi
done
我想遍历当前文件夹中的每个文件,并检查它是否与特定扩展名匹配。上面的代码不起作用,你知道为什么吗?
答案 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 matching
或test
(这是{{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"
它将找到扩展名为tex
,png
和pdf
的文件。