Bash Shell显示当前目录下的所有隐藏文件,你只想查看目录下的隐藏(点号)文件,然后编辑其中一个已经忘记名字的文件,或者删除一些废弃文件。ls -a
可以显示出包括隐藏文件在内的所有文件,但这种输出往往包含了过多干扰项,而ls -a .*
的结果也比你想象或需要的更多。
解决方案
使用 ls -d
配合筛选条件。例如:
ls -d .*
ls -d .b*
ls -d .[!.]*
ls -d .*/
因为每个正常的目录中都包含 .
和..
,所以就没必要再显示了。你可以用 ls -A 列出目录中除这两个文件外的其余所有文件。对于可以利用通配符(也就是模式)列出文件的命令,下面给出了能够将.
和 ..
排除在外的通配符写法:
$ grep -l 'PATH' ~/.[!.]*
/home/jp/.bash_history
/home/jp/.bash_profile
$
讨论
鉴于 shell 处理文件通配符的方式,.*
的行为并不符合你的预期。文件名扩展或通配符匹配(globbing)1 的工作方式如下:任何包含字符 *、?
或[
的字符串均被视为模式,会被依字母排序的、匹配该模式的文件名列表所替换。*
可以匹配包括空串在内的任意字符串,?
可以匹配任意单个字符。[]
内出现的字符形成了一个字符列表或范围,可以匹配其中的任意字符。还有其他各种扩展模式匹配操作符,我们就不在此展开细说了。因此,*.txt
表示以.txt
结尾的所有文件,*txt
表示以 txt 结尾的所有文件(模式中没有点号)。f?o
可以匹配 foo 或 fao,但无法匹配 fooo。有鉴于此,你可能认为.*
会匹配以点号开头的所有文件。
这里特别说明一下 globbing 和 wildcard 的区别:globbing 是对 wildcard 进行扩展的过程。在贝尔实验室诞生的 Unix 中,有一个名为 glob(global 的简写)的独立程序(/etc/glob)。早期 Unix 版本(第 1~6 版,1969—1975 年)的命令解释器(也就是 shell)都要依赖于该程序扩展命令中未被引用的 wildcard,然后将扩展后的结果提供给命令执行。因此,本文将 globbing 译为通配符匹配,将 wildcard 译为通配符。另外,正文中的“扩展模式匹配”是指,如果使用内建命令 shopt 启用了 shell 选项 extglob,那么 shell 就能够识别一些扩展模式匹配操作符,如?(pattern-list)、*(pattern-list)、+(pattern-list)
等。——译者注
问题在于.*
还可以匹配目录.
和..
(存在于每个目录中),它们会和其他以点号开头的文件名一同显示出来。如果 ls 的参数是目录名,那么除了目录名之外,它还会列出该目录中的内容。因此,当你使用ls .*
时,得到的可不仅仅是当前目录下的点号文件,还包括当前目录(.)
下的所有文件和子目录、父目录(..)
下的所有文件和子目录、当前目录下以点号开头的子目录名及其内容。这种结果可以说非常杂乱,而且通常也用不着这么多输出。
你可以用同样的 ls 命令实验一下,看看加上 -d 选项和没有 -d 选项的区别,然后试试echo .*
。echo 命令只会简单地显示出扩展.*
后的结果,这些结果就是 ls 命令的参数。
接着还可以试试echo .[!.]*
。.[!.]*
是文件名扩展模式,其中[]
指定了要匹配的字符列表,但是开头的!
对该列表做了求反操作。因此我们要找的是一个点号,然后是除点号外的任意字符,接着是任意数量的任意字符。^
也可以实现相同的求反效果,但 ! 是 POSIX 标准中规定的,可移植性更好。
ls 命令中的一种特殊情况也能帮上忙。如果指定了 -d 选项,同时文件名模式以斜线结尾,那么 ls 命令只显示匹配模式的目录,匹配的文件名一概不显示。例如:
$ ls -d .v*
.vim .viminfo .vimrc
$ ls -d .v*/
.vim
$
第一条命令显示出以.v
开头的 3 个文件名,如果其中有目录,也不会列出其内容(因为使用了 -d 选项)。第二条命令在模式结尾加上了斜线(.v*/)
,因此 ls 命令只显示匹配该模式的目录,在这种情况下,符合条件的只有目录.vim
。
如果你在命令ls -d .v*/
的输出中看到了两条斜线:
$ ls -d .v*/
.vim//
$
这可能是因为你执行的是加入了 -F 选项的 ls 别名。在命令名前面使用反斜线就可以避开所有的别名:
$ \ls -d .v*/
.vim/
$
有些文件名很难匹配。.[!.]*
会漏掉名为..foo
的文件。你可以加上形如.??*
的模式来匹配以点号开头且长度至少为 3 个字符的文件名,但是 ls -d .[!.]* .??*
会将同时匹配这两种模式的文件名显示两遍。但如果只使用.??*
,又会漏掉像.a
这样的文件:
$ touch ..foo .a .normal_dot_file normal_file
$ ls -a
. .. ..foo .a .normal_dot_file normal_file
$ ls -d .??*
..foo .normal_dot_file
$ ls -d .[!.]*
.a .normal_dot_file
$ ls -d .[!.]* .??* | sort -u
..foo
.a
.normal_dot_file
具体用哪一种取决于你的需求和环境,没有什么通用的解决方案。
如果 ls 命令损坏或不知何故无法使用,那么可以用echo *
作为一种应急替代。这种方法可行的原因是,shell 会将 *
扩展为当前目录下的所有文件,其结果和 ls 差不多。
酷客网相关文章:
评论前必须登录!
注册