ls 命令列出 POSIX 系统上的文件。它是一个简单的命令,经常被低估,不是因为它的功能(因为它实际上只做一件事),而是因为你如何优化它的使用。
在 10 个最重要的终端命令中,谦逊的 ls 命令排在前三名,因为 ls 不只是列出文件,它还告诉你关于它们的重要信息。它告诉你诸如谁拥有文件或目录、每个文件何时丢失或修改,甚至是什么类型的文件。然后它还附带有一个附加功能,可以让你了解你在哪里,附近有什么对象,以及你可以用它们做什么。
如果你的 ls 经验仅限于你的发行版在 .bashrc 中为其设置的别名,那么你可能错失了很多。
GNU 还是 BSD?
在了解 ls 的隐藏功能之前,你必须确定你正在运行哪个 ls 命令。两个最流行的版本是 GNU 版本(包含在 GNU coreutils 包中)和 BSD 版本。如果你运行的是 Linux,那么你可能已经安装了 ls。如果你运行的是 BSD 或 MacOS,那么你拥有 BSD 版本。两者之间存在差异,本文会对此进行说明。
你可以使用 --version 选项来查找你的计算机上安装的版本。
$ ls --version
如果这返回关于 GNU coreutils 的信息,那么你拥有 GNU 版本。如果它返回一个错误,那么你可能正在运行 BSD 版本(运行 man ls | head 以确认)。
你还应该调查你的发行版可能已经设置了哪些预设。终端命令的自定义通常放在 $HOME/.bashrc 或 $HOME/.bash_aliases 或 $HOME/.profile 中,并且通过将 ls 别名设置为更复杂的 ls 命令来实现。例如:
alias ls='ls --color'
发行版提供的预设非常有帮助,但是它们使得难以辨别 ls 本身的功能以及其附加选项提供的功能。如果你想运行 ls 而不是别名,你可以使用反斜杠来“转义”该命令:
$ \ls
分类
单独运行时,ls 只是以尽可能多的列来列出终端中的文件。
$ ls ~/example
bunko jdk-10.0.2
chapterize otf2ttf.ff
despacer overtar.sh
estimate.sh pandoc-2.7.1
fop-2.3 safe_yaml
games tt
这是有用的信息,但是没有图标的便利性来快速传达哪个是目录,或者文本文件,或者图像等等,所有这些文件看起来基本上都一样。
使用 -F(或 GNU 上的 --classify)在每个条目之后显示指示符,以标识文件的类型:
$ ls ~/example
bunko jdk-10.0.2/
chapterize* otf2ttf.ff*
despacer* overtar.sh*
estimate.sh pandoc@
fop-2.3/ pandoc-2.7.1/
games/ tt*
使用此选项,你终端中列出的项目会使用以下简写方式按文件类型进行分类:
- 斜杠 (/) 表示目录(或“文件夹”)。
- 星号 (*) 表示可执行文件。这包括二进制文件(编译的代码)以及脚本(具有可执行权限的文本文件)。
- at 符号 (@) 表示符号链接(或“别名”)。
- 等号 (=) 表示套接字。
- 在 BSD 上,百分号 (%) 表示一个 whiteout(某些文件系统上删除文件的一种方法)。
- 在 GNU 上,尖括号 (>) 表示门(Illumos 和 Solaris 上的进程间通信)。
- 竖线 (|) 表示 FIFO。
此选项的更简单版本是 -p,它仅区分文件和目录。
长列表
从 ls 获取“长列表”非常常见,以至于许多发行版将 ll 别名为 ls -l。 长列表格式提供许多重要的文件属性,例如权限、拥有每个文件的用户、文件所属的组、文件大小(以字节为单位)以及文件上次更改的日期:
$ ls -l
-rwxrwx---. 1 seth users 455 Mar 2 2017 estimate.sh
-rwxrwxr-x. 1 seth users 662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users 20697793 Jun 29 2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth users 6210 May 22 10:22 geteltorito
-rwxrwx---. 1 seth users 177 Nov 12 2018 html4mutt.sh
[...]
如果你不习惯以字节为单位,请添加 -h 标志(或 GNU 中的 --human)以将文件大小转换为更人性化的表示法:
$ ls --human
-rwxrwx---. 1 seth users 455 Mar 2 2017 estimate.sh
-rwxrwxr-x. 1 seth seth 662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users 20M Jun 29 2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth seth 6.1K May 22 10:22 geteltorito
-rwxrwx---. 1 seth users 177 Nov 12 2018 html4mutt.sh
你可以通过使用 -o 仅显示所有者列,或使用 -g 仅显示组列来查看略少的信息:
$ ls -o
-rwxrwx---. 1 seth 455 Mar 2 2017 estimate.sh
-rwxrwxr-x. 1 seth 662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth 20M Jun 29 2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth 6.1K May 22 10:22 geteltorito
-rwxrwx---. 1 seth 177 Nov 12 2018 html4mutt.sh
组合这两个选项以都不显示。
时间和日期格式
ls 的长列表格式通常如下所示:
-rwxrwx---. 1 seth users 455 Mar 2 2017 estimate.sh
-rwxrwxr-x. 1 seth users 662 Apr 29 22:27 factorial
-rwxrwx---. 1 seth users 20697793 Jun 29 2018 fop-2.3-bin.tar.gz
-rwxrwxr-x. 1 seth users 6210 May 22 10:22 geteltorito
-rwxrwx---. 1 seth users 177 Nov 12 2018 html4mutt.sh
月份的名称不容易排序,无论是计算上还是(取决于你的大脑倾向于喜欢字符串还是整数)通过识别。 你可以使用 --time-style 选项加上格式名称来更改时间戳的格式。 可用的格式包括:
- full-iso (1970-01-01 21:12:00)
- long-iso (1970-01-01 21:12)
- iso (01-01 21:12)
- locale(使用你的区域设置)
- posix-STYLE(将 STYLE 替换为区域定义)
你还可以使用 date 命令的正式表示法创建自定义样式。
按时间排序
通常,ls 命令按字母顺序排序。 你可以使用 -t 选项使其根据哪个文件最近被更改(最新的文件首先列出)来排序。
例如:
$ touch foo bar baz
$ ls
bar baz foo
$ touch foo
$ ls -t
foo bar baz
列表类型
ls 的标准输出在可读性和空间效率之间取得平衡,但有时你希望你的文件列表采用特定的排列方式。
对于逗号分隔的文件列表,使用 -m:
ls -m ~/example
bar, baz, foo
要强制每行显示一个文件,请使用 -1 选项(这是数字 1,而不是小写 L):
$ ls -1 ~/bin/
bar
baz
foo
要按文件扩展名而不是文件名对条目进行排序,请使用 -X(这是一个大写 X):
$ ls
bar.xfc baz.txt foo.asc
$ ls -X
foo.asc baz.txt bar.xfc
隐藏杂乱
在某些 ls 列表中有一些你可能不关心的条目。例如,元字符 . 和 .. 分别代表“这里”和“返回上一层”。如果你熟悉在终端中导航,你可能已经知道每个目录都将自身称为 . 并将父目录称为 ..,因此当你使用 -a 选项显示隐藏文件时,你不需要经常被提醒这一点。
要显示几乎所有隐藏文件(排除 . 和 ..),请使用 -A 选项:
$ ls -a
.
..
.android
.atom
.bash_aliases
[...]
$ ls -A
.android
.atom
.bash_aliases
[...]
使用许多好的 Unix 工具,有一种传统是通过在要保存的文件的名称后附加一些特殊字符来保存备份文件。例如,在 Vim 中,备份会以附加到名称后的 ~ 字符来保存。
这些类型的备份文件已经在许多场合将我从愚蠢的错误中拯救出来,但是在享受它们提供的安全感多年之后,我不需要视觉证据证明它们的存在。 我相信 Linux 应用程序会生成备份文件(如果它们声称会这样做),并且我很高兴相信它们的存在。
要从视图中隐藏备份文件,请使用 -B 或 --ignore-backups 来隐藏常见的备份格式(此选项在 BSD ls 中不可用):
$ ls
bar.xfc baz.txt foo.asc~ foo.asc
$ ls -B
bar.xfc baz.txt foo.asc
当然,备份文件仍然存在;它只是被过滤掉,因此你不必查看它。
GNU Emacs 保存备份文件(除非另有配置)在文件名的开头和结尾带有哈希字符 (#)(#file#)。 其他应用程序可能会使用不同的样式。 使用什么模式并不重要,因为你可以使用 --hide 选项创建自己的排除项:
$ ls
bar.xfc baz.txt #foo.asc# foo.asc
$ ls --hide="#*#"
bar.xfc baz.txt foo.asc
使用递归列出目录
除非你专门对该目录运行 ls,否则 ls 命令不会列出目录的内容:
$ ls -F
example/ quux* xyz.txt
$ ls -R
quux xyz.txt
./example:
bar.xfc baz.txt #foo.asc# foo.asc
使用别名使其成为永久性的
ls 命令可能是任何给定 shell 会话中使用最频繁的命令。 它是你的眼睛和耳朵,为你提供上下文并确认命令的结果。 虽然拥有许多选项很有用,但 ls 的部分美妙之处在于它的简洁:两个字符和回车键,你就确切地知道你在哪里以及附近有什么。 如果你必须停下来思考(更不用说输入)几个不同的选项,它就会变得不那么方便,因此通常即使是最有用的选项也会被省略。
解决方案是为你的 ls 命令设置别名,以便在使用它时,你获得你最关心的信息。
要在 Bash shell 中为命令创建别名,请在你的主目录中创建一个名为 .bash_aliases 的文件(你必须在开头包含点)。 在此文件中,列出你要为其创建别名的命令,然后列出你要创建的别名。 例如:
alias ls='ls -A -F -B --human --color'
此行导致你的 Bash shell 将 ls 命令解释为 ls -A -F -B --human --color。
你不限于重新定义现有命令。 你可以创建自己的别名:
alias ll='ls -l'
alias la='ls -A'
alias lh='ls -h'
要使别名生效,你的 shell 必须知道 .bash_aliases 配置文件存在。 在编辑器中打开 .bashrc 文件(或者如果它不存在,则创建它),并包含此代码块:
if [ -e $HOME/.bash_aliases ]; then
source $HOME/.bash_aliases
fi
每次加载 .bashrc 时(也就是每次启动新的 Bash shell 时),Bash 都会将 .bash_aliases 加载到你的环境中。 你可以关闭并重新启动你的 Bash 会话,或者只是强制它现在这样做:
$ source ~/.bashrc
如果你忘记是否给某个命令设置了别名,which 命令会告诉你。
$ which ls
alias ls='ls -A -F -B --human --color'
/usr/bin/ls
如果你使用选项给 ls 命令本身设置了别名,你可以随时通过在 ls 前面加上反斜杠来覆盖你自己的别名。例如,在示例别名中,备份文件使用 -B 选项隐藏,这意味着无法使用 ls 命令来备份文件。覆盖别名以查看备份文件。
$ ls
bar baz foo
$ \ls
bar baz baz~ foo
做一件事,并把它做好。
ls 命令有数量惊人的选项,其中许多选项是特定于特定用途的,或者高度依赖于你使用的终端。在 GNU 系统上查看 info ls,或者在 GNU 或 BSD 系统上查看 man ls 以获取更多选项。
你可能会觉得奇怪,一个以每个工具“做一件事,并把它做好”为前提而闻名的系统,会用 50 个选项来加重其最常用的命令。但是 ls 确实只做一件事:它列出文件。并且拥有 50 个选项来允许你控制接收列表的方式,ls 将其唯一的工作做得非常、非常好。
12 条评论