首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否存在类似tcsh的shopt设置或设置组合?

是否存在类似tcsh的shopt设置或设置组合?
EN

Unix & Linux用户
提问于 2018-08-06 23:49:58
回答 1查看 768关注 0票数 8

我正在从一个长时间的tcsh用户过渡到一个新的bash用户(它已经过期了)。我定期在tcsh中编写了许多foreach循环,因此我学习了bash的for循环的语法,但当不匹配的glob模式作为文字字符串在循环中传递时,我感到很惊讶。我搜索了一种改变这种行为的方法,以便跳过文字字符串并找到shopt -s nullglob。我的理解是,理论上这应该等同于tcsh的行为方式,但今天我发现了一个不同之处。当我执行ls ../*.doesnotmatch时,结果是当前目录的内容列表。具体来说,我是这样做的:

bash:

代码语言:javascript
复制
$ shopt -s nullglob
$ ls ../*.sam
extractSplitReads_BwaMem    extractSplitReads_BwaMem.xml
$ shopt -u nullglob
$ ls ../*.sam
ls: ../*.sam: No such file or directory

父目录中没有与*.sam匹配的内容,尤其是当前目录。一开始我真的很困惑,但后来我意识到glob模式正在消失,命令的执行就好像我没有提供任何参数一样,例如:

代码语言:javascript
复制
$ ls

因此,我尝试单独设置failglob和使用nullglob,但是只要设置了failglob,任何不匹配的glob模式都会杀死命令,不管是否存在匹配的模式:

bash:

代码语言:javascript
复制
$ 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:

代码语言:javascript
复制
$ 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的工作方式。

EN

回答 1

Unix & Linux用户

发布于 2018-08-07 03:52:39

与文件名扩展相关的唯一shopt选项是dotglobfailglobnocaseglobnullglob,而且它们(单独或合并)似乎都不完全符合您的要求。太可惜了,因为这听起来真的是个好主意。

我的建议是在交互式会话中设置failglob,这样您就可以避免可能不需要的命令,例如:

代码语言:javascript
复制
mv -r file1 file2 dir1 dir2 destination-*-dir

如果file1file2dir1不匹配,并且设置了nullglob,那么destination-*-dir将被移动到dir2中。

另一方面,在shell脚本编写时完全依赖文件名扩展并不是一个好主意。建议始终验证这种扩展是否存在,以及它们应该是什么样的。

我是说,不是这么做的:

代码语言:javascript
复制
rm -- *.jpg *.txt

最好这样做:

代码语言:javascript
复制
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匹配,但它实际上是一个目录,也是安全的。

票数 5
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/460920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档