为什么 ls .* 显示的文件与 ls ./.* 不同?

为什么 ls .* 显示的文件与 ls ./.* 不同?

当前目录下存在空白文件.ignoramus。

bojan@localhost:~$ echo $GLOBIGNORE
.ignoramus
bojan@localhost:~$ ls .* | grep ignor
bojan@localhost:~$ ls ./.* | grep ignor
./.ignoramus

使用的工具 ls (GNU coreutils) 8.23 GNU bash,版本 4.3.42(1)-release (x86_64-pc-linux-gnu)

答案1

当 shell 在命令行中扩展通配符时,该$GLOBIGNORE设置将由 shell 进行处理。在第一种情况下,shell 首先扩展.*.ignoramus,它与 匹配$GLOBIGNORE,因此它不包含在传递给 的名称中ls

在第二种情况下,外壳扩展./.*./.ignoramus,即不是匹配于$GLOBIGNORE.如果您设置$GLOBIGNORE为,.ignoramus:./.ignoramus那么第二个命令的行为将与第一个命令匹配。

答案2

简短原因:字符串./.ignoramus不匹配.ignoramus

简短的解决方案:使用GLOBIGNORE=*ignoramus(另请参阅最后的详细信息)。

$ GLOBIGNORE=*ignoramus
$ ls .* | grep ignor                 ### empty
$ ls ./.* | grep ignor               ### also empty

/星号将匹配任何内容(甚至是名称前面的斜杠)。
当然,这也会匹配foobar.ignoramus。有关一些解决方法,请参阅最后。


扩展答案:

普通文件也会发生这种情况:

$ mkdir /tmp/mytest; cd /tmp/mytest
$ touch f1 f2 filetotest
$ GLOBIGNORE=filetotest
$ ls -1
f1
f2
filetotest

$ ls -1 f*
f1
f2

$ ls -1 *
f1
f2

$ ls -1 ./f*
./f1
./f2
./filetotest

GLOBIGNORE 不会匹配./filetotest,但如果我们使用:

$ GLOBIGNORE="*filetotest"
$ ls -1 ./f*
./f1
./f2

$ ls -1 ./*
./f1
./f2

$ ls -1
f1
f2
filetotest

GLOBIGNORE 中的模式将匹配(something)filetotest

对于你的例子:

$ touch .ignoramus
$ GLOBIGNORE='*ignoramus'
ls -1a
.
..
f1
f2
filetotest
.ignoramus

$ ls .* | grep ignor
$ ls ./.* | grep ignor

即使文件前面有一些路径,它也可以工作:

$ GLOBIGNORE='*ignoramus:*filetotest'
$ mkdir -p long/dir/to/test
$ touch long/dir/to/test/{f3,f4,.ignoramus,.other,filetotest}

$ ls -1 long/dir/to/test/f*
long/dir/to/test/f3
long/dir/to/test/f4

$ ls -1 long/dir/to/test/.[^.]*
long/dir/to/test/.other

$ shopt -s dotglob
$ ls -1 long/dir/to/test/*
long/dir/to/test/f3
long/dir/to/test/f4
long/dir/to/test/.other

$ unset GLOBIGNORE; shopt -s dotglob
$ ls -1 long/dir/to/test/*
long/dir/to/test/f3
long/dir/to/test/f4
long/dir/to/test/filetotest
long/dir/to/test/.ignoramus
long/dir/to/test/.other

当然,这也会匹配bar.ignoramus。如果不需要,请使用:

$ GLOBIGNORE=.ignoramus:./.ignoramus

或者,如果您想要包含任何路径:

$ GLOBIGNORE=.ignoramus:*/.ignoramus

相关内容