在 Bash 脚本中忽略具有特定模式的文件

在 Bash 脚本中忽略具有特定模式的文件

我尝试忽略以 开头的文件名,33266158I因为这些文件是空的,不需要任何处理。我刚刚粘贴了忽略文件的部分。

但这不起作用,只有文件名33266158I被忽略,但没有33266158I1

  FILENAME_IGNORE='33266158I*'
  if [ $M_GID != $FILENAME_IGNORE ]; then  #Ignore Problematic GID,Temp Soln

这是忽略以 开头的文件的正确方法吗33266158I1

答案1

[

你可能知道也可能不知道,但让我们明确一点:[不是语法的一部分if。我的意思if [ …是 的行为类似于if true或,其中、和是命令。它们返回退出状态,这对 来说很重要。if falseif any_command[truefalseany_commandif

即使[它是内置命令(Bash 中确实如此),它的行为也像常规命令一样。甚至还有一个独立的[可执行文件(例如/usr/bin/[),因为它是 POSIX 所要求的。

这意味着[ foo != bar ]只是一个[带有几个参数的命令。是的,]只是一个参数,它不是分隔符或类似的东西。命名的命令[只需要是]它的最后一个参数(这样代码更清晰)。有一个等效命令test,几乎就像一个别名:[ foo != bar ]相当于test foo != bar

您的[ $M_GID != $FILENAME_IGNORE ]代码被正常解析,变量被扩展。$FILENAME_IGNORE扩展为33266158I*,然后发生单词拆分和文件名生成(因为变量没有被双引号引起来)。$M_GID出于同样的原因,不加引号也可能造成危害。

我真的很惊讶“只有文件名33266158I被忽略,但没有33266158I1”。如果这两个文件位于当前工作目录中,33266158I*应该扩展为(至少)33266158I 33266158I1解释为两个单词。我希望[: too many arguments

无论发生什么,在之后(或一般情况下)使用未加引号的变量[并不是一个好的做法。

如果您引用了变量(即如果您使用[ "$M_GID" != "$FILENAME_IGNORE" ]那么$FILENAME_IGNORE将扩展为33266158I*而不会进一步扩展。但是整个命令不会执行您想要的操作,因为!=(或=)中的[(或test)不执行任何模式匹配。在这种情况下,中的星号33266158I*只是一个文字星号。


[[

在 Bash 中有[[。人们经常会误以为[[[是等价的,但事实并非如此。所有可以用 进行的测试都[可以用 进行[[,但反之则不行。区别:

  • [[可以做得更多;
  • [[是一个关键字,它与 shell 解析器集成,它改变了一些规则,它实际上知道 和 之间的变量和[[引号]]
  • [[虽然是,但不可移植[

在您的情况下,重要的是!=如果[[其中的通配符没有被引用,则会将其右侧字符串视为模式。此代码片段:

[[ $M_GID != $FILENAME_IGNORE ]]

应该做你想做的事。这是 Bash 中为数不多的可以使用变量的地方之一(这里$M_GID可能不加引号,另一个变量(此处$FILENAME_IGNORE应该不加引号(我的意思是如果你加双引号,$FILENAME_IGNORE那么它的值将不会被视为模式)。只是因为[[它与 shell 解析器集成在一起。

在 中[[,运算符=!=使用通配符模式(这些带有?*),与目录中的实际文件没有任何联系。还有=~,它使用正则表达式(带有..*)。


GLOBIGNORE

如果$M_GID你的代码来自一个 glob,比如

for M_GID in *; do

然后忽略一些名字完全地(即让它们在任何迭代中都不会出现在扩展中$M_GID)你可以使用GLOBIGNORE

shellGLOBIGNORE变量可用于限制与模式匹配的文件名集。如果设置了,则从匹配列表中删除GLOBIGNORE每个匹配的文件名,这些文件名也与 中的一个模式匹配。[…]GLOBIGNORE

就你的情况而言:

GLOBIGNORE='33266158I*'
for M_GID in *; do

笔记:

  • 看什么文档说明了匹配以点 ( .) 开头的文件名以及如何GLOBIGNORE改变默认行为。
  • unset GLOBIGNORE在执行另一个(不相关的)匹配之前不要忘记这一点。

相关内容