![在 Bash 脚本中忽略具有特定模式的文件](https://linux22.com/image/1623201/%E5%9C%A8%20Bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E5%BF%BD%E7%95%A5%E5%85%B7%E6%9C%89%E7%89%B9%E5%AE%9A%E6%A8%A1%E5%BC%8F%E7%9A%84%E6%96%87%E4%BB%B6.png)
我尝试忽略以 开头的文件名,33266158I
因为这些文件是空的,不需要任何处理。我刚刚粘贴了忽略文件的部分。
但这不起作用,只有文件名33266158I
被忽略,但没有33266158I1
。
FILENAME_IGNORE='33266158I*'
if [ $M_GID != $FILENAME_IGNORE ]; then #Ignore Problematic GID,Temp Soln
这是忽略以 开头的文件的正确方法吗33266158I1
答案1
[
你可能知道也可能不知道,但让我们明确一点:[
不是语法的一部分if
。我的意思if [ …
是 的行为类似于if true
或,其中、和是命令。它们返回退出状态,这对 来说很重要。if false
if any_command
[
true
false
any_command
if
即使[
它是内置命令(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
:
shell
GLOBIGNORE
变量可用于限制与模式匹配的文件名集。如果设置了,则从匹配列表中删除GLOBIGNORE
每个匹配的文件名,这些文件名也与 中的一个模式匹配。[…]GLOBIGNORE
就你的情况而言:
GLOBIGNORE='33266158I*'
for M_GID in *; do
…
笔记:
- 看什么文档说明了匹配以点 (
.
) 开头的文件名以及如何GLOBIGNORE
改变默认行为。 unset GLOBIGNORE
在执行另一个(不相关的)匹配之前不要忘记这一点。