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
递归添加子文件夹,
for i in `find . -name "*.java" -type f`; do
echo "$i"
done
遍历所有以: .img
, .bin
, .txt
suffix 结尾的文件,并打印文件名:
for i in *.img *.bin *.txt;
do
echo "$i"
done
Or in a recursive manner (find also in all subdirectories):
for i in `find . -type f -name "*.img" -o -name "*.bin" -o -name "*.txt"`;
do
echo "$i"
done
正确答案是@chepner's
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 与固定字符串进行比较。
要扩展和纠正这种情况,您应该将 [[ ]] 与正则表达式运算符一起使用 =~
例如:
for i in $(ls);do
if [[ $i =~ .*\.java$ ]];then
echo "I want to do something with the file $i"
fi
done
=~ 右侧的正则表达式针对左侧运算符的值进行测试,不应被引用,(引用不会出错,但会与固定字符串进行比较,因此很可能会失败”
但是@chepner 上面使用 glob 的答案是一种更有效的机制。
我同意其他关于循环文件的正确方法的答案。然而,OP问:
上面的代码不起作用,你知道为什么吗?
是的!
一篇优秀的文章What is the difference between test, [ 和 [[ ?]详细解释了在其他差异中,您不能在命令中使用expression matching
or (这是 的简写)pattern matching
test
[
功能新测试[[旧测试[示例 模式匹配 =(或 ==)(不可用)[[ $name = a* ]] || echo "名称不以 'a' 开头:$name" 正则表达式 =~(不可用)[[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "今天是 13 号星期五!" 匹配
所以这就是你的脚本失败的原因。如果 OP 对[[
语法的答案感兴趣(其缺点是在与命令一样多的平台上不受支持[
),我很乐意编辑我的答案以包含它。
编辑:有关如何将答案中的数据格式化为表格的任何提示都会有所帮助!
I found this solution to be quite handy. It uses the -or
option in find
:
find . -name \*.tex -or -name "*.png" -or -name "*.pdf"
It will find the files with extension tex
, png
, and pdf
.