我正在从一个长时间的tcsh用户过渡到一个新的bash用户(它已经过期了)。我定期在tcsh中编写了许多foreach循环,因此我学习了bash的for循环的语法,但当不匹配的glob模式作为文字字符串在循环中传递时,我感到很惊讶。我搜索了一种改变这种行为的方法,以便跳过文字字符串并找到shopt -s nullglob。我的理解是,理论上这应该等同于tcsh的行为方式,但今天我发现了一个不同之处。当我执行ls ../*.doesnotmatch时,结果是当前目录的内容列表。具体来说,我是这样做的:
bash:
$ shopt -s nullglob
$ ls ../*.sam
extractSplitReads_BwaMem extractSplitReads_BwaMem.xml
$ shopt -u nullglob
$ ls ../*.sam
ls: ../*.sam: No such file or directory父目录中没有与*.sam匹配的内容,尤其是当前目录。一开始我真的很困惑,但后来我意识到glob模式正在消失,命令的执行就好像我没有提供任何参数一样,例如:
$ ls因此,我尝试单独设置failglob和使用nullglob,但是只要设置了failglob,任何不匹配的glob模式都会杀死命令,不管是否存在匹配的模式:
bash:
$ shopt -s failglob
$ shopt -s nullglob
$ ls ../vis*/*.xml
../visualization/LAJ.xml
$ ls ../vis*/*.xml ../*.sam
bash: no match: ../*.sam
$ ls ../{vis*/*.xml,*.sam}
bash: no match: ../*.sam当我使用tcsh时,所有的globs都归结为那些匹配的东西,如果没有匹配,则会得到一个glob错误:
tcsh:
$ ls ../vis*/*.xml ../*.sam
../visualization/LAJ.xml
$ ls ../{vis*/*.xml,*.sam}
../visualization/LAJ.xml
$ ls ../*.sam
ls: No match.我查看了商店的设置,但我找不到得到这种行为的方法。我是不是遗漏了什么?除了bash或tcsh之外,还有另一个像tcsh那样对待globs的现代shell吗?我希望在某些东西匹配时使用nullglob的行为,但是在没有匹配的情况下,则需要failglob的行为,这似乎就是tcsh的工作方式。
发布于 2018-08-07 03:52:39
与文件名扩展相关的唯一shopt选项是dotglob、failglob、nocaseglob和nullglob,而且它们(单独或合并)似乎都不完全符合您的要求。太可惜了,因为这听起来真的是个好主意。
我的建议是在交互式会话中设置failglob,这样您就可以避免可能不需要的命令,例如:
mv -r file1 file2 dir1 dir2 destination-*-dir如果file1、file2和dir1不匹配,并且设置了nullglob,那么destination-*-dir将被移动到dir2中。
另一方面,在shell脚本编写时完全依赖文件名扩展并不是一个好主意。建议始终验证这种扩展是否存在,以及它们应该是什么样的。
我是说,不是这么做的:
rm -- *.jpg *.txt最好这样做:
for file in *.jpg *.txt; do
if [ -f "${file}" ]; then
rm -- "${file}"
fi
done
# Or this (non-POSIX, as it uses an array)
for file in *.jpg *.txt; do
if [ -f "${file}" ]; then
files_to_delete+=( "${file}" )
fi
done
if [ "${#files_to_delete[@]}" -gt 0 ]; then
rm -- "${files_to_delete[@]}"
fi这样,即使某些文件与*.txt匹配,但它实际上是一个目录,也是安全的。
https://unix.stackexchange.com/questions/460920
复制相似问题