Answers:
ls
列出要作为参数传递的目录的文件和目录内容,如果没有给出参数,则列出当前目录。还可以通过许多影响其行为的选项(man ls
有关详细信息,请参见)。
如果ls
传递了一个名为的参数*
,它将*
在当前目录中查找一个名为的文件或目录,并像其他任何目录一样列出它。ls
不会*
以任何其他方式对待角色。
但是,如果ls *
是一个外壳命令行,则该外壳将其扩大*
根据相应的外壳的通配符(也被称作文件名生成或文件名扩展)的规则。
尽管不同的外壳支持不同的globing运算符,但大多数都同意最简单的一个*
。*
模式代表任意数量的字符,因此*
a glob
将扩展到与该模式匹配的当前目录中的文件列表。但是,有一个例外,即.
文件名中的前导点()字符必须显式匹配,因此*
实际上扩展为不是以.
(按字典顺序)开头的文件和目录列表。
举例来说,如果当前目录包含一个称为文件.
,..
,.foo
,-l
和foo bar
,*
将由外壳扩展到两个参数传递给ls
:-l
和foo bar
,所以这将是,如果你输入了:
ls -l "foo bar"
要么
'ls' "-l" foo\ bar
这是运行完全相同的命令的三种方式。在这3种情况下,该ls
命令(可能会从中/bin/ls
提到的目录中执行$PATH
)都将传递这3个参数:“ ls”,“-l”和“ foo bar”。
顺便说一句,在这种情况下,ls
将第一个(严格来说讲第二个)作为选项。
现在,正如我所说,不同的外壳具有不同的全局操作符。几十年前,zsh
引入了**/
运算符¹,它表示要匹配任何级别的子目录,简称,(*/)#
并且***/
与之相同,只是它在降序时遵循符号链接。
几年前(2003年7月ksh93o+
),ksh93
决定复制该行为,但决定使其为可选项,并且仅涵盖了这种**
情况(未涉及***
)。另外,尽管**
单独使用并没有什么特别之处zsh
(与*
其他传统shell一样,它的含义相同,因为它**
意味着任意数量的字符后接任意数量的字符),但在ksh93中,**
含义相同**/*
(因此当前目录下的任何文件或目录都一样) (不包括隐藏文件)。
bash
ksh93
在几年后(2009年2月,bash 4.0)复制,具有相同的语法,但不幸的**
是:bash 类似于zsh
的***
,即递归到子目录时遵循符号链接,这通常不是您想要的,会产生讨厌的副作用。它在bash-4.3中已部分修复,因为仍然遵循符号链接,但递归在那里停止了。它已在5.0中完全修复。
yash
已**
在2008年的2.0版中添加,并启用了该extended-glob
选项。它的实现更接近zsh
,因为**
它并不特殊。在2.15版(2009)中,它添加了***
in zsh
和两个自己的扩展名:.**
并.***
在递归时包括隐藏的目录(在中zsh
,D
glob限定符(如**/*(D)
)将考虑隐藏的文件和目录,但是如果您只想遍历隐藏的目录目录,但不展开隐藏文件,您需要((*|.*)/)#*
或**/[^.]*(D)
)。
该鱼外壳也支持**
。与的早期版本一样bash
,在降级目录树时,它也会遵循符号链接。但是在该外壳中**/*
与并不相同**
。**
更大的扩展*
是可以跨越多个目录。在fish
,**/*.c
将匹配a/b/c.c
而不是a.c
,同时a**.c
将匹配a.c
和ab/c/d.c
和zsh
的**/.*
,例如已被写入.* **/.*
。在那里,***
被理解为**
与之*
相同**
。
tcsh
globstar
在V6.17.01(2010年5月)中还添加了一个选项,并支持**
和***
àla zsh
。
所以tcsh
,bash
和ksh93
,(当相应的选项启用(globstar
)),或者fish
,**
扩展所有低于当前的文件和目录,并且***
是一样**
的fish
,一个符号链接遍历**
了tcsh
与globstar
,和同为*
中bash
和ksh93
(尽管它这些shell的未来版本也将遍历符号链接并非没有可能)。
在上面,您已经注意到有必要确保没有将任何扩展解释为选项。为此,您可以这样做:
ls -- *
要么:
ls ./*
在某些命令中(对于没关系ls
),第二个命令更可取,因为即使使用了--
一些文件名,它们也可能会被特殊对待。-
对于大多数文本实用程序而言,情况就是这样,cd
并且pushd
包含例如=
字符的文件名也是如此awk
。./
在所有参数之前加上它们将删除其特殊含义(至少对于上述情况而言)。
还应当指出的是,大部分炮弹有一些影响的通配符行为的选项(如点文件是否被忽略与否,排序顺序,做什么,如果没有匹配...),也见$FIGNORE
参数ksh
此外,在每一个外壳,但csh
,tcsh
,fish
和zsh
,如果文件名匹配模式不匹配任何文件,该模式被作为引起混乱,并可能错误未扩展参数传递。例如,如果当前目录中没有非隐藏文件
ls *
实际上会调用ls
两个参数ls
和*
。而且由于根本没有文件,因此也没有任何文件*
,您会看到ls(不是shell)发出的错误消息,例如:ls: cannot access *: No such file or directory
,它使人们认为这ls
实际上是在扩展全局范围。
在以下情况下,问题甚至更严重:
rm -- *.[ab]
如果没有*.a
,也没有*.b
文件在当前目录下,那么你可能最终删除一个名为*.[ab]
错误(csh
,tcsh
,和zsh
将报告不匹配错误,并不会要求rm
(和fish
不支持[...]
通配符))。
如果确实要将文字传递*
给ls
,则必须以或或的*
某种方式引用该字符。在类似POSIX的shell中,可以使用或一起禁用globing (除非在/ 仿真中,否则后者不起作用)。ls \*
ls '*'
ls "*"
set -o noglob
set -f
zsh
sh
ksh
¹尽管(*/)#
一直受到支持,但它首先像..../
zsh-2.0(甚至可能在以前)中是简写****/
形式,然后是2.1 ,然后在2.2中获得确定的形式**/
(1992年初)
find -name *
。特别是使用更复杂的模式时,如果当前目录中只有一个匹配项,人们通常不会意识到他们没有将星号传递给find
。
*.[ab]
将尝试删除以结尾的所有内容.[ab]
。[
鱼不是特别的。
该命令ls
默认为ls .
:列出当前目录中的所有条目。
该命令的ls *
意思是“在*
shell模式的扩展上运行ls ”
该*
模式由外壳程序处理,并扩展到当前目录中的所有条目,但以.
。开头的条目除外。它将深入一层。
双重或三重*
模式的解释取决于实际使用的外壳。
*
是匹配0个或多个字符的通配符。一些现代的shell将在看到**
模式后递归到子目录中。
*
功能外,请参阅其他答案来解释globstar。还应该明确的是,ls 与星号无关,它根本没有经过任何这些星号。运行echo ls *
以查看编写时将执行的操作ls *
。
您可以通过键入echo
而不是ls
第一个来使整个过程神秘化,以查看命令扩展到的内容:
$ echo *
Applications Downloads Documents tmp.html
因此,在这种情况下,ls *
扩展为ls Applications Downloads Documents tmp.html
$ echo **
Applications Downloads Documents tmp.html
$ echo ***
Applications Downloads Documents tmp.html
所以没有变化。假设您使用的bash
是您的外壳程序-大多数人都是这样,并且不同的外壳程序具有不同的行为。如果您使用ash
或csh
或ksh
或zsh
,则可能会期望事情有所不同。这就是拥有不同外壳的要点。
因此,让我们尝试一些不同的事情(仍然使用bash
),以便我们了解一下globlob(*
)运算符可以为我们做些什么。例如,我们可以按名称的一部分进行过滤:
$ echo D*
Downloads Documents
有趣的是,斜杠是任何目录名称的隐含部分。因此*/
将仅产生目录(以及目录的符号链接):
$ echo */
Applications/ Downloads/ Documents/
我们可以通过在中间添加斜线来在多个级别进行一些过滤:
$ echo D*/*/
Documents/Work/ /Documents/unfinished/
由于该Downloads
目录不包含任何子目录,因此它不会最终出现在输出中。这对于仅检查所需文件非常有用。我一直在使用这样的命令:
$ ls -l /home/*/public_html/wp-config.php
如果有的话,它将列出wp-config.php
任何用户public_html
目录的基本级别上存在的所有文件。或者可能更完整:
$ find /home/*/public_html/ -name wp-config.php
这样可以wp-config.php
在任何用户的public_html
目录或其子目录中找到任何文件,但它的运行效率将远远高于仅find /home/ -name wp-config.php
检查每个用户的目录,而不是检查任何public_html
目录。
bash
是外壳程序”←,并且未启用globstar。shopt -s globstar
然后再试一次...
set -x
,它将开始打印每次执行的“实际”命令(使用关闭set +x
)。
在某些shell中,包括globstar
启用了该选项的bash 4.x ,**
将执行递归glob,降级匹配的目录。其他星号不会进一步修改此操作。
ksh93
和相反zsh
,bash
它确实会遍历递归中的符号链接,这通常是不希望的。