Linux 中的 ls 命令:解释 17 个有用示例
Linux 中的 ls 命令是最常用的命令之一。但大多数人并没有充分发挥其潜力。查看 Linux 中的基础知识和高级 ls 命令示例。
ls 命令是我们在发现 shell 时首先学习的命令之一。之后,无论您的技能水平如何,它都将仍然是最常用的之一。
尽管很受欢迎,但我们很少超越 -l
、-d
和 -a
选项。不幸的是,因为典型的 ls 实现有数十个可用选项!因此,我建议您跟随我寻找 ls 命令隐藏的瑰宝。
我们在此 ls 命令指南中使用的示例文件层次结构
在深入讨论问题的核心之前,我们需要做一些准备:如果没有一些目录可供使用,就很难研究 ls 命令。为了使您能够在计算机上尝试本文中给出的命令,以下是如何创建我将在所有示例中使用的示例文件层次结构。只需将该命令列表复制粘贴到您的终端,您就准备好了:
mkdir ls
cd ls
# Create a hidden file:
echo You can not see me > .hidden
# Create a couple of 2MiB files:
dd if=/dev/zero of=a bs=1M count=2
dd if=/dev/zero of=b bs=1M seek=1 count=1
# Create few sub-directories
mkdir -p dir/subdir dir/subdir2
# Create a bunch of empty files
touch c dir/{d,e,f} dir/subdir/{g,h,i} dir/subdir2/{j,k,l}
# Create few links (hard and symbolic)
ln dir/e hardlink-to-file
ln -s dir/f symlink-to-file
ln -s dir/subdir symlink-to-subdir
如果您在使用这些命令时遇到任何问题,请随时使用评论部分寻求帮助。假设现在一切就绪,是时候深入讨论我们的主题了。
ls 命令的著名用例
由于每个旅程都从第一步开始,让我们首先回顾一下 ls 命令的基本用例。当然,如果您认为自己是专家,请随时跳到更高级的部分。但如果你现在更愿意和我在一起,那就太好了:你可能会学到一两件事!
<无选项>
:默认行为
ls 命令提供有关命令行上给出的路径所指向的每个类文件对象的信息。当没有任何选项使用时:
显示的唯一信息是路径指向的类文件对象的名称;
如果该路径指向一个目录(或指向目录的符号链接),则 ls 命令还会列出该目录的内容;
如果显示多个条目,则它们按文件名的字母顺序排序。
最后,当命令行上没有给出路径时,ls
命令假定 ./
——即当前目录。
现在让我们看看所有这些规则的实际应用:
# display the content of the current directory
sh:~/ls$ ls ./
a c e hardlink-to-file symlink-to-file
b dir f link-to-subdir symlink-to-subdir
# without any option, `ls` is equivalent
# to `ls ./`
sh:~/ls$ ls
a c e hardlink-to-file symlink-to-file
b dir f link-to-subdir symlink-to-subdir
# entries are sorted alphabetically
# ("dir/f" starts with a "d" so it is before "e")
sh:~/ls$ ls c b e dir/f a
a b c dir/f e
# when a command line argument is a directory
# (or a symbolic link to a directory)
# displays its content
sh:~/ls$ ls a b c link-to-subdir dir
a b c
dir:
d e f subdir subdir2
link-to-subdir:
g h i
-d
:不列出目录内容
使用 -d
选项,ls
不再显示命令行上给出的目录内容,而是将目录条目视为文件条目。我们来比较一下:
# Default behavior: display the content of the `dir` directory
sh:~/ls$ ls a dir b
a b
dir:
d e f subdir subdir2
# `-d` option: directories are handled like files
sh:~/ls$ ls -d a dir b
a b dir
单独使用 -d
选项时,ls
和普通的 echo
命令之间没有太大区别:
# In both case, the `*` glob pattern is expanded by
# the shell, which also takes care of
# sorting entries in the alphabetical order
sh:~/ls$ ls -d *
a b c dir hardlink-to-file symlink-to-file symlink-to-subdir
sh:~/ls$ echo *
a b c dir hardlink-to-file symlink-to-file symlink-to-subdir
但是,当与另一个选项关联以显示额外信息时,-d
选项变得更加有用,例如使用我们现在将看到的 -l
标志时。
-l
:长格式选项
在 ls
选项流行度竞赛中,-l
(小写 ell 字母)选项可能会成为获胜者。它非常有用,以至于许多系统都为 ls -l
(或 ls -l
)提供了 ll
别名。
-l
代表长格式。使用该选项,ls
命令将在其自己的行上显示每个条目,其中包含以下信息: * 文件模式 * 链接数 * 所有者名称 * 组名 * 文件中的字节数 * 日期和时间 * 路径名
此外,使用 -l
选项,ls
将不再遵循符号链接。因此,它将显示有关链接本身的信息(文件模式、链接数量等),而不是有关其目的地的信息。出于同样的原因,ls
命令不会显示符号链接指向的目录的内容:
# Default behavior: displays only the filename and
# follows symbolic links:
sh:~/ls$ ls *
a b c e f hardlink-to-file symlink-to-file
dir:
d e f subdir subdir2
link-to-subdir:
g h i
symlink-to-subdir:
g h i
# `-l` option: displays extended informations and
# no longer follows symbolic links
sh:~/ls$ ls -l *
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 b
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 22:18 c
-rw-r--r-- 3 sylvain sylvain 0 Sep 19 22:18 e
lrwxrwxrwx 1 sylvain sylvain 5 Sep 19 12:09 f -> dir/f
-rw-r--r-- 3 sylvain sylvain 0 Sep 19 22:18 hardlink-to-file
lrwxrwxrwx 1 sylvain sylvain 10 Sep 19 12:09 link-to-subdir -> dir/subdir
lrwxrwxrwx 1 sylvain sylvain 5 Sep 19 22:18 symlink-to-file -> dir/f
lrwxrwxrwx 1 sylvain sylvain 10 Sep 19 22:18 symlink-to-subdir -> dir/subdir
dir:
total 8
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 22:18 d
-rw-r--r-- 3 sylvain sylvain 0 Sep 19 22:18 e
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 22:18 f
drwxr-xr-x 2 sylvain sylvain 4096 Sep 19 12:09 subdir
drwxr-xr-x 2 sylvain sylvain 4096 Sep 19 12:09 subdir2
作为本节的总结,我让您检查通过组合 -l
和 -d
选项获得的输出:
sh:~/ls$ ls -ld *
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 b
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 22:18 c
drwxr-xr-x 4 sylvain sylvain 4096 Sep 19 12:09 dir
-rw-r--r-- 3 sylvain sylvain 0 Sep 19 22:18 e
lrwxrwxrwx 1 sylvain sylvain 5 Sep 19 12:09 f -> dir/f
-rw-r--r-- 3 sylvain sylvain 0 Sep 19 22:18 hardlink-to-file
lrwxrwxrwx 1 sylvain sylvain 10 Sep 19 12:09 link-to-subdir -> dir/subdir
lrwxrwxrwx 1 sylvain sylvain 5 Sep 19 22:18 symlink-to-file -> dir/f
lrwxrwxrwx 1 sylvain sylvain 10 Sep 19 22:18 symlink-to-subdir -> dir/subdir
-a
:显示所有文件
使用 -a
选项,ls
在显示目录内容时包含隐藏文件。但什么是隐藏文件呢?
按照惯例,在类 Unix 系统上,名称以点开头的文件被视为隐藏文件。此外,每个目录还包含两个特殊的、通常隐藏的条目:.
和 ..
在每个目录中:
.
条目指向目录本身。这种自我参照可能看起来很奇怪。但它有时很有用,有点像将您自己的电话号码存入您的智能手机库中。..
条目指向父目录。由于类 Unix 系统上的文件层次结构严格组织为树,因此每个目录都有一个且只有一个父目录。也许除了根目录/
?嗯,不是真的:根目录的父目录是……根目录本身。
# Default behavior: do not display hidden entries
# (including . and ..)
sh:~/ls$ ls
a c e hardlink-to-file symlink-to-file
b dir f link-to-subdir symlink-to-subdir
# `-a` option: show hidden files and directories
sh:~/ls$ ls -a
. a c e hardlink-to-file link-to-subdir symlink-to-subdir
.. b dir f .hidden symlink-to-file
ls 命令的有用选项
在回顾了众所周知的 -l
、-d
和 -a
选项之后,让我们将注意力转向几个不太为人所知的选项。发现特别有用。
-s
:显示分配的大小
您可能还记得 -l
选项显示文件中的字节数。 -s
选项显示分配的大小(以块为单位)。什么是块?嗯,一组字节,其大小取决于实现。在 BSD 上通常为 512 字节,在 Linux 上通常为 1024 字节。
当我已经可以访问以字节为单位的大小时,为什么还要为以块为单位的大小而烦恼?那么,-s
选项显示分配的 大小。不是文件的逻辑大小。对于稀疏文件来说,这可能是两个完全不同的事情。稀疏文件是包含“漏洞”的文件。读取时,这些漏洞的行为就像仅包含零的普通文件块。但它们实际上不占用磁盘空间。我们可以使用带有 seek
选项的 dd 命令来创建稀疏文件,就像我对示例层次结构中的 b
文件所做的那样:
sh:~/ls$ ls -ls a b
2052 -rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 a
1028 -rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 22:18 b
如您所见,我的 a
和 b
文件的长度似乎都是 2 MB。但 b
文件很稀疏,只占用磁盘上的 1028 个块(大约 1 MB)。
-h
显示人类可读的尺寸
使用 -h
选项,ls
将使用单位后缀显示文件大小,使其更加用户友好。此选项仅在与 -l
选项(Linux、BSD)或 -s
(Linux) 结合使用时才有意义:
sh:~/ls$ ls -lsh a b
2.1M -rw-r--r-- 1 sylvain sylvain 2.0M Sep 19 22:18 a
1.1M -rw-r--r-- 1 sylvain sylvain 2.0M Sep 19 22:18 b
openbsd-6.3$ ls -lsh a b
4128 -rw-r--r-- 1 sylvain sylvain 2.0M Sep 19 23:49 a
2112 -rw-r--r-- 1 sylvain sylvain 2.0M Sep 19 23:49 b
您可能已经注意到,大小是使用 1024 单位的幂显示的,其中 K 代表 2^10=1024 字节,M 代表 1024^2=1048576 字节,依此类推。这里值得一提的是,作为 GNU Coreutils 的一部分提供的 ls 实现有一个额外的 --si 选项来使用 1000 次方而不是 1024 次方:
sh:~/ls$ ls -lsh --si a b
2.2M -rw-r--r-- 1 sylvain sylvain 2.1M Sep 19 22:18 a
1.1M -rw-r--r-- 1 sylvain sylvain 2.1M Sep 19 22:18 b
-i
显示inode编号
在 Unix 风格的文件系统上,inode 编号(或 POSIX 术语中的文件序列号)是唯一标识文件系统对象(文件、目录、命名管道,...)。使用 -i
选项,ls
命令将在每个路径旁边显示其 inode 编号。
即使它看起来有些奇怪,我发现自己时不时地使用 -i
选项,尤其是识别引用同一文件系统对象的目录条目。您主要在研究硬链接或绑定安装时使用该选项。观看该视频以获取实际示例:https://youtu.be/Jp58Osb1uFo?t=140
sh:~/ls$ ls -i *
8222 a 8243 b 8262 c 8264 hardlink-to-file 8272 symlink-to-file
dir:
8263 d 8264 e 8265 f 8245 subdir 8261 subdir2
symlink-to-subdir:
8266 g 8267 h 8268 i
在上面的示例中,您可以看到每个文件名都以与该路径关联的索引节点号为前缀。在您的系统上,数字肯定会有所不同。无论如何,请仔细查看 hardlink-to-file
和 dir/e
条目。两者都有相同的 inode 号(在我的例子中是 8264)。这意味着它们是引用相同底层文件系统对象的两个条目——事实上,这就是硬链接的确切定义。
您可能还记得我之前说过根目录的父目录是根目录本身。通过使用 -i
选项,验证该断言非常容易:
openbsd-6$ ls -id /
2 /
openbsd-6$ ls -ia /
2 . 25985 bin 5 dev 77954 sbin
2 .. 1235 boot 51969 etc 10 sys
8 .cshrc 1240 bsd 2 home 7 tmp
9 .profile 1241 bsd.booted 77953 mnt 2 usr
51968 altroot 4 bsd.rd 26016 root 78016 var
正如您所看到的,在我的系统上,根目录与索引节点号 2 关联,这也是其父目录的索引节点。这样就证明了根目录是它自己的父目录。
ls 命令很少使用的选项
我经常使用上一节中描述的选项,但我现在要讨论的选项......好吧......我知道它们存在。然而我必须承认,当我需要它们时,我经常不得不看man
来刷新我的记忆。
-L
:显示符号链接目标的信息
当应用于符号链接时,此选项会修改 ls 命令的行为。使用 -L
选项,ls
将显示有关符号链接的目标的信息,而不是显示那些与符号链接本身相关的。通过检查以下示例,差异将很明显:
# Pay special attention to the permission
# and file size for symbolic links with and without
# the `-L` option:
sh:~/ls$ ls -ld *
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 b
-rw-r--r-- 1 sylvain sylvain 0 Sep 20 00:09 c
drwxr-xr-x 4 sylvain sylvain 4096 Sep 20 00:09 dir
-rw-r--r-- 2 sylvain sylvain 0 Sep 20 00:09 hardlink-to-file
lrwxrwxrwx 1 sylvain sylvain 5 Sep 20 00:09 symlink-to-file -> dir/f
lrwxrwxrwx 1 sylvain sylvain 10 Sep 20 00:09 symlink-to-subdir -> dir/subdir
sylvain@bulbizarre:/tmp/ls/ls/ls$ ls -lLd *
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 b
-rw-r--r-- 1 sylvain sylvain 0 Sep 20 00:09 c
drwxr-xr-x 4 sylvain sylvain 4096 Sep 20 00:09 dir
-rw-r--r-- 2 sylvain sylvain 0 Sep 20 00:09 hardlink-to-file
-rw-r--r-- 1 sylvain sylvain 0 Sep 20 00:09 symlink-to-file
drwxr-xr-x 2 sylvain sylvain 4096 Sep 20 00:09 symlink-to-subdir
-F
:在文件名后附加分类字符
-F
选项在某些类别的文件系统对象的路径名后添加一个额外的字符来标识它们。它将添加:
每个目录路径名后面有一个
\
,每个路径名后面的
@
是一个符号链接,每个可执行文件后面有一个
*
,每个 FIFO 后面都有一个
|
(有关更多信息,请参阅mkfifo
)
在我早期的 Unix 时代,我经常使用这个选项。但由于 ls 可以对其输出进行着色(而且我们有彩色显示器!),所以我很少需要它。但我记得。有时,我会在远程终端上找到使用它的机会:
sh:~/ls$ ls -F
a b c dir/ hardlink-to-file symlink-to-file@ symlink-to-subdir@
t
:按修改时间排序条目
使用 -t
选项,ls
命令显示按修改时间排序的目录条目(最近的在前),而不是按名称排序:
# Default sort order (by filename)
sh:~/ls$ ls
a b c dir hardlink-to-file symlink-to-file symlink-to-subdir
# Sort by modification date
sh:~/ls$ ls -t
symlink-to-subdir symlink-to-file c dir hardlink-to-file b a
如果我更改文件,它现在将显示为列表中的第一个(即:最近修改的)条目:
sh:~/ls$ echo >> a
sh:~/ls$ ls -t
a symlink-to-subdir symlink-to-file c dir hardlink-to-file b
-S
:按大小排序条目
使用 -S
选项,ls
将显示按大小排序的条目,最大的文件首先显示。如果出现平局,条目将根据其路径名进行排序:
sh:~/ls$ ls -lS
total 6244
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 b
drwxr-xr-x 4 sylvain sylvain 512 Sep 19 23:49 dir
lrwxr-xr-x 1 sylvain sylvain 10 Sep 19 23:49 symlink-to-subdir -> dir/subdir
lrwxr-xr-x 1 sylvain sylvain 5 Sep 19 23:49 symlink-to-file -> dir/f
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 23:49 c
-rw-r--r-- 2 sylvain sylvain 0 Sep 19 23:49 hardlink-to-file
-r
:反向排序
此选项反转排序顺序。我发现与 -t
选项关联时最有用,可以首先显示最近最少修改的文件,或者与 -S
选项关联时首先显示最小的文件。但它也适用于默认的、按路径名、排序顺序:
# Display the least recently modified file first
sh:~/ls$ ls -rt
b hardlink-to-file dir c symlink-to-file symlink-to-subdir a
# Display the smallest file first
sh:~/ls$ ls -rS
hardlink-to-file c symlink-to-file symlink-to-subdir dir b a
# Display path names in reversed alphabetical order
sh:~/ls$ ls -r
symlink-to-subdir symlink-to-file hardlink-to-file dir c b a
-n
:显示数字 UID/GID
此选项与 -l
选项完全相同 — 除了使用 -n
时,所有者的组 ID (GID) 和用户 ID (UID) 显示为数字而不是使用他们的相关名称:
sh:~/ls$ ls -ld a b c /
drwxr-xr-x 28 root root 4096 May 6 00:28 /
-rw-r--r-- 1 sylvain sylvain 2097153 Sep 20 00:45 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 b
-rw-r--r-- 1 sylvain sylvain 0 Sep 20 00:09 c
sh:~/ls$ ls -nd a b c /
drwxr-xr-x 28 0 0 4096 May 6 00:28 /
-rw-r--r-- 1 1000 1000 2097153 Sep 20 00:45 a
-rw-r--r-- 1 1000 1000 2097152 Sep 20 00:09 b
-rw-r--r-- 1 1000 1000 0 Sep 20 00:09 c
ls 命令的真正奇特用法
没有人可以声称自己知道一切。在撰写本文时,我(重新)发现了几个 ls 选项。我不记得自己用过它们,但也许你用过?如果是这样,我很想在评论部分中阅读您认为它们在哪些情况下有用。无论如何,这里有一个您可能会感兴趣的选择。
-R
:递归列出子目录
默认情况下,ls
命令仅显示命令行上明确给出的目录的内容。使用-R
选项,它还会递归显示遇到的目录的内容:
sh:~/ls$ ls -R
.:
a b c dir hardlink-to-file symlink-to-file symlink-to-subdir
./dir:
d e f subdir subdir2
./dir/subdir:
g h i
./dir/subdir2:
j k l
虽然理论上很有趣,但我发现(双关语)由 find .
命令生成的输出为此目的更具可读性。但当然,您的里程可能会有所不同:
sh:~/ls$ find .
.
./c
./.hidden
./hardlink-to-file
./b
./symlink-to-subdir
./dir
./dir/d
./dir/e
./dir/subdir2
./dir/subdir2/l
./dir/subdir2/j
./dir/subdir2/k
./dir/subdir
./dir/subdir/g
./dir/subdir/i
./dir/subdir/h
./dir/f
./symlink-to-file
./a
-A
:显示几乎所有文件
虽然 POSIX 标准中没有定义,但 -A
选项出现在 GNU 和 BSD 世界中。在这两种情况下,它的工作方式类似于 -a
,但不包括 .
和 ..
条目。值得一提的是,在 BSD 系统上,-A
暗示着超级用户:
sh:~/ls$ ls -a
. a c hardlink-to-file symlink-to-file
.. b dir .hidden symlink-to-subdir
sh:~/ls$ ls -A
a b c dir hardlink-to-file .hidden symlink-to-file symlink-to-subdir
openbsd-6.3$ su root
openbsd-6.3# ls
.hidden a b c dir hardlink-to-file symlink-to-file symlink-to-subdir
-f
:不排序
使用 -f
选项,ls
将按照条目在目录中出现的顺序显示条目。该顺序取决于底层文件系统,并且创建文件的顺序,因此很难预测。 -f
选项也意味着 -a
选项:
sh:~/ls$ ls -f
.. .hidden b dir a
c hardlink-to-file symlink-to-subdir symlink-to-file .
openbsd-6$ ls -f
. a c symlink-to-subdir
.. b hardlink-to-file
.hidden dir symlink-to-file
有趣的是,在 GNU Coreutils 8.26 ls
实现中,如果拼写为 ,则可以使用
——但如果你写成-l
和 -f
选项-fl-lf
则不会。在 OpenBSD 上,两者都按预期工作:
sh:~/ls$ ls -lf
.. .hidden b dir a
c hardlink-to-file symlink-to-subdir symlink-to-file .
sh:~/ls$ ls -fl
total 3100
drwxr-xr-x 3 sylvain sylvain 4096 Sep 19 12:09 ..
-rw-r--r-- 1 sylvain sylvain 0 Sep 20 00:09 c
-rw-r--r-- 1 sylvain sylvain 19 Sep 20 00:09 .hidden
-rw-r--r-- 2 sylvain sylvain 0 Sep 20 00:09 hardlink-to-file
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 20 00:09 b
lrwxrwxrwx 1 sylvain sylvain 10 Sep 20 00:09 symlink-to-subdir -> dir/subdir
drwxr-xr-x 4 sylvain sylvain 4096 Sep 20 00:09 dir
lrwxrwxrwx 1 sylvain sylvain 5 Sep 20 00:09 symlink-to-file -> dir/f
-rw-r--r-- 1 sylvain sylvain 2097153 Sep 20 00:45 a
drwxr-xr-x 3 sylvain sylvain 4096 Sep 20 00:09 .
openbsd-6$ ls -lf
total 6256
drwxr-xr-x 3 sylvain sylvain 512 Sep 19 23:49 .
drwxr-xr-x 5 sylvain sylvain 512 Sep 19 23:49 ..
-rw-r--r-- 1 sylvain sylvain 19 Sep 19 23:49 .hidden
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 b
drwxr-xr-x 4 sylvain sylvain 512 Sep 19 23:49 dir
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 23:49 c
-rw-r--r-- 2 sylvain sylvain 0 Sep 19 23:49 hardlink-to-file
lrwxr-xr-x 1 sylvain sylvain 5 Sep 19 23:49 symlink-to-file -> dir/f
lrwxr-xr-x 1 sylvain sylvain 10 Sep 19 23:49 symlink-to-subdir -> dir/subdir
openbsd-6$ ls -fl
total 6256
drwxr-xr-x 3 sylvain sylvain 512 Sep 19 23:49 .
drwxr-xr-x 5 sylvain sylvain 512 Sep 19 23:49 ..
-rw-r--r-- 1 sylvain sylvain 19 Sep 19 23:49 .hidden
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 a
-rw-r--r-- 1 sylvain sylvain 2097152 Sep 19 23:49 b
drwxr-xr-x 4 sylvain sylvain 512 Sep 19 23:49 dir
-rw-r--r-- 1 sylvain sylvain 0 Sep 19 23:49 c
-rw-r--r-- 2 sylvain sylvain 0 Sep 19 23:49 hardlink-to-file
lrwxr-xr-x 1 sylvain sylvain 5 Sep 19 23:49 symlink-to-file -> dir/f
lrwxr-xr-x 1 sylvain sylvain 10 Sep 19 23:49 symlink-to-subdir -> dir/subdir
-q
:将不可打印的文件名字符显示为?
在 Unix 风格的文件系统上,文件名可以包含除 \
和 NUL 字符之外的任何字符。这意味着文件名可能包含无法打印的字符,甚至可能会干扰您的终端的控制序列。让我们尝试一些有趣的事情:
touch "$(echo -e '\x1B[7mBOO\x1B[0m')"
显然,该文件名包含不可打印的字符。在 ls
的现代实现中,当输出是终端时,会隐含 -q
选项,以避免潜在的恶意影响。因此不可打印的字符将被替换为问号:
sh:~/ls$ ls *BOO*
?[7mBOO?[0m
然而,如果你这样写,事情就会不同:
# I let you try that by yourself
# to not spoil the fun;)
sh:~/ls$ ls *BOO* | cat
<代码>| cat 毫无用处,但作为一个副作用,ls
命令现在在其标准输出上看到一个管道,而不是 tty(“终端”)。由于输出不再是终端,因此不再隐含 -q
选项,并且 ls
将逐字显示文件名。在这种情况下,如果一切按预期工作,则会以时髦的视频效果呈现文件名。
显式使用 -q
选项可以解决这个问题。我会让您自己尝试(并最终尝试其他 ANSI 转义序列)。但我借此机会警告您不要在 shell 脚本中使用 ls 命令。实际上,ls
是为“人类消费”而设计的。有许多关于特制文件名的附带情况很难正确处理。如果您需要浏览文件列表,我强烈建议您使用 find 命令。在最简单的情况下,一个简单的 for
循环就足够了 - 但这是另一个故事了。
for f in *; do echo "$f"; done
结束?
我们对 ls 命令选项的了解到此结束。不用说,它远非详尽无遗,我试图在这里重点关注最有用和最便携的选项。但是每个 ls 实现都有其很酷的功能,因此,如果您知道我在本文中错过的一些不错的选项,请随时使用评论部分与我们分享。如果我们有足够的反馈,我们甚至可以将它们汇编并发布在后续文章中!
说到 ls 命令,你知道 lsof 命令吗?它与 ls 无关,但它告诉您哪个用户正在访问某个文件。