为什么 ls -d 还列出文件,它记录在哪里?

为什么 ls -d 还列出文件,它记录在哪里?
  • 指定时应ls --directory a*仅列出以以下内容开头的目录a*
  • 但它列出了以以下开头的文件和目录a

问题:

  • man除了我认为我彻底查看过的地方之外,我可以在哪里找到有关此问题的一些文档info
  • 这仅适用于 BASH 吗?

答案1

a*and语法*a*是由 shell 实现的,而不是由ls命令实现的。

当您输入时

ls a*

在 shell 提示符下,shell 会展开a*为当前目录中名称以a.例如,它可能扩展a*到序列a1 a2 a3,并将它们作为参数传递给ls。命令ls本身永远看不到*角色;它只看到三个参数a1a2a3

出于通配符扩展的目的,“文件”指当前目录中的所有实体。例如,a1可能是普通文件,a2可能是目录,也a3可能是符号链接。它们都有目录条目,并且 shell 的通配符扩展并不关心这些条目引用的实体类型。

实际上,您可能遇到的所有 shell(bash、sh、ksh、zsh、csh、tcsh...)都实现了通配符。细节可能有所不同,但*匹配零个或多个字符以及?匹配任何单个字符的基本语法相当一致。

特别是对于 bash,这在 bash 手册的“文件名扩展”部分中有记录;运行info bash并搜索“文件名扩展”,或者查看这里

事实上,这是由 shell 而不是单个命令完成的,这会产生一些有趣(有时令人惊讶)的后果。最好的一点是,通配符处理对于(几乎)全部命令;如果 shell 不这样做,不可避免地有些命令不会打扰,而其他命令会以作者认为“更好”的微妙不同的方式来完成。 (我认为Windows命令shell有这个问题,但我对它还不够熟悉,无法进一步评论。)

另一方面,编写一个命令来重命名多个文件是很困难的。如果你写:

mv *.log *.log.bak

它可能会失败,因为它*.log.bak是根据当前目录中已存在的文件进行扩展的。有一些命令可以执行此类操作,但它们必须使用自己的语法来指定如何重命名文件。某些命令(例如find)可以进行自己的通配符扩展;你必须引用参数来抑制 shell 的扩展:

find . -name '*.txt' -print

shell 的通配符扩展完全基于命令行参数的语法和现有文件集。它不能受命令含义的影响。例如,如果要将所有.log文件移至父目录,可以键入:

mv *.log ..

如果您忘记了..

mv *.log

.log并且当前目录中恰好有两个文件,它将扩展为:

mv one.log two.log

这将重命名one.log并破坏two.log.

编辑:在 52 票赞成、1 票接受和一枚大师徽章之后,也许我实际上应该回答标题中的问题。

-d或选项--directory并不ls告诉它仅列出目录。它告诉它像目录一样列出目录,而不是目录的内容。如果您将目录名称作为参数提供ls,默认情况下它将列出内容目录的名称,因为这通常是您感兴趣的内容。该-d选项告诉它仅列出目录本身。当与通配符结合使用时,这会特别有用。如果您输入:

ls -l a*

ls将为您提供每个的长列表文件名字以a, 开头的内容每个以 开头的目录a。如果您只想要文件和目录的列表(每个文件和目录占一行),则可以使用:

ls -ld a*

这相当于:

ls -l -d a*

再次记住,该ls命令永远不会看到该*字符。

至于记录在哪里,将向您展示几乎任何类 Unix 系统上man ls该命令的文档。ls在大多数基于 Linux 的系统上,该ls命令是 GNU coreutils 软件包的一部分;如果您有info命令,或者info lsinfo coreutils ls应该为您提供更明确和全面的文档。其他系统,例如MacOS,可能使用不同版本的命令ls,也可能没有该info命令;对于这些系统,请使用man ls.并ls --help会显示一个相对地简短的使用消息(我的系统上有 117 行)如果您正在使用 GNU coreutils 实现。

是的,即使是专家也需要时不时地查阅文档。也可以看看这个经典笑话

答案2

参见基思·汤普森的回答;但要解释为什么ls --directory a*显示文件目录:该--directory选项不抑制非目录文件。相反,它会按原样列出目录,而否则会列出其内容。例子:

$ mkdir foo
$ touch foo/bar
$ ls foo
bar
$ ls --directory foo
foo

答案3

非常明确地说,它记录在ls(1) 手册页:

-d, --目录 列出目录条目而不是内容,并且不取消引用符号链接

公平地说,“条目而不是内容”可能更具解释性:

如果 FILE 是目录,则显示目录条目本身,而不是列出该目录的内容。如果 FILE 是符号链接,则显示链接条目本身,而不是链接指向的文件。

答案4

文档没有说它列出了仅有的目录条目 bur 相反,当ls收到目录名称时,它会列出目录条目代替这是内容。最好的理解方法是通过示例:

> {ice} ~ :10:47 % ls -l / 
total 97
drwxr-xr-x   2 root root  4096 May  3 00:27 bin
drwxr-xr-x   4 root root  1024 May  3 14:17 boot
drwxr-xr-x   2 root root  4096 Apr 29 13:44 cdrom
drwxr-xr-x  18 root root  4420 May  9 09:58 dev
...
lrwxrwxrwx   1 root root    33 May  3 14:16 vmlinuz -> boot/vmlinuz-3.9.0-030900-generic
lrwxrwxrwx   1 root root    29 May  3 11:07 vmlinuz.old -> boot/vmlinuz-3.8.0-19-generic
> {ice} ~ :10:47 % ls -ld /
drwxr-xr-x 25 root root 4096 May  3 14:16 /

相关内容