“dir”和“ls”终端命令有什么区别?

我一直在尝试找出在终端中使用dirls命令的区别。我知道ls是查看目录中文件的传统UNIX方法,而dir是Windows命令提示符的等效命令,但这两个命令都可以在终端中使用。
如果我输入dir,它会显示目录中的文件和文件夹;如果我输入ls,它也会显示相同的内容,只是带有内容高亮。这两个命令都接受选项(例如ls -adir -a都会返回所有文件、文件夹和隐藏文件)。
那么,有人知道它们之间的区别以及为什么同时使用dirls吗?

8dir --color ;-) - Rinzwind
3只是想说,我对这个问题获得的回应数量感到惊讶。看来我不是唯一一个对此感到好奇的人 :) - BretD
3古时候的命令总是能把老一辈的书呆子拖出来;) - Rinzwind
"dir"和"ls"有什么区别? - phuclv
5个回答

dirlscoreutils的一部分,dirls几乎相同,只是具有不同的默认选项。

GNU核心工具是GNU操作系统的基本文件、Shell和文本处理工具。这些是期望存在于每个操作系统上的核心工具。

info dir说:

dir等同于ls -C -b;也就是说,默认情况下文件以列形式垂直排序,并且特殊字符以反斜杠转义序列表示。

哦,还有vdirinfo vdir说:

vdir等同于ls -l -b;也就是说,默认情况下文件以长格式显示,并且特殊字符以反斜杠转义序列表示。

很可能dir存在是为了向后兼容或由于历史原因。


我在想,这可能只是另一个名称而已。我猜想这样做的原因是为了让Windows用户感到更亲切,哈哈。非常感谢你详尽的回答! - BretD
4输入alias dir查看它的实际内容。输入alias查看所有别名。 - user606723
2@user606723,“alias dir”在11.10中没有显示(至少对我来说不是)。我相信“alias”只显示本地用户别名设置,而不是系统范围内的。 - James
输入 type dir 查看它是什么(别名、命令、bash函数...) - ychaouche

lsdir之间的关系

lsdir是两个独立的程序,它们的行为类似。如下所解释和引用的,dir的目的是提供一个像ls一样的命令,其输出不会因为是否发送到终端而有所变化。为了实现这一点,dir必须以一种合理且对于在终端上查看和写入文件或管道都有用的方式格式化其输出。

关于dir有两个常见的误解:

许多人认为dirls的别名,但事实并非如此。这两个命令没有任何关联,并且在Ubuntu中,默认情况下dir根本不是一个别名。lsdir是由不同的、非相同的可执行文件提供的。
许多人认为dir之所以存在,是出于模糊的历史原因或为了与某些标准或其他操作系统兼容。事实并非如此。 ls的行为方式是为了兼容性。 dir不需要兼容性,因为它不是一个标准的Unix命令,开发者们认为它的替代行为有自己的价值,甚至可能更可取。
好了,但是lsdir到底有什么区别呢? lsdir都可以列出目录的内容。它们在默认行为上有两个具体区别来区分它们。
当其标准输出为终端时,ls以垂直排序的列方式列出文件名(类似于ls -C)。当其标准输出不是终端(例如文件或管道)时,ls每行列出一个文件名(类似于ls -1)。
无论其标准输出是否为终端,dir以垂直排序的列方式列出文件名(类似于ls -C)。
对于lsdir,这些默认设置可以通过--format=标志和-1-C-m-x标志进行覆盖,这些标志缩写了特定的--format=选项。有关详细信息,请参阅10.1.4 通用输出格式化GNU coreutils参考手册中。
当其标准输出为终端且要列出的文件名包含控制字符时,ls会打印?代替每个控制字符(类似于ls -q)。当其标准输出不是终端时,ls会原样打印控制字符(类似于ls --show-control-chars)。
无论其标准输出是否为终端,当dir遇到控制字符或任何其他在shell中输入时会被特殊解释的字符时,它会打印字符的反斜杠序列。这甚至包括相对常见的字符,如空格。例如,dir将把名为Documents backups的条目列为Documents\ backups。这类似于ls -b
对于lsdir,这些默认设置可以通过10.1.7 格式化文件名中列出的标志进行覆盖,在GNU coreutils参考手册中。其中包括-b-q--quoting-style=和其他一些标志。

来源: ls调用dir调用, 在GNU coreutils参考手册中。

为什么需要dir

关于单独使用dir的理由在4.5 接口标准GNU编码标准中有详细说明。我建议阅读整个章节以了解开发者的推理,但以下是与ls/dir相关的要点:

请不要让实用程序的行为依赖于调用它时使用的名称...... 相反,使用运行时选项或编译开关或两者都使用来选择替代行为...... 同样,请不要让命令行程序的行为依赖于输出设备的类型...... 兼容性要求某些程序依赖于输出设备的类型。如果ls或sh不按照所有用户的期望方式进行操作,那将是灾难性的。在其中一些情况下,我们会提供一个首选的替代版本,该版本不依赖于输出设备的类型。例如,我们提供了一个类似于ls的dir程序,只是其默认输出格式始终为多列格式。
GNU项目从技术角度考虑,不希望一个实用程序根据写入的设备类型产生不同的输出(至少在实用程序的默认配置下)。对于一些实用程序,包括ls命令,设备相关的输出是必要的,以确保与用户的预期相符。有些用户也特别喜欢这种设备相关的行为。
虽然ls命令无法合理地实现设备无关性,但创建了一个单独的dir实用程序来实现这一点。因此,dir命令并非出于历史兼容性原因而表现奇怪的实用程序,而是ls命令。

要查看在coreutils源代码中如何实现lsdir和相关的vdir实用程序,而不会出现不必要的代码重复,请参阅ls-dir.cls-ls.cls-vdir.cls.hls.c

dir真的有用吗?

如果你曾经希望即使将ls通过管道传递给lessls | less)或重定向到文件(ls > out.txt),它也能产生多列输出,那么你可以使用dirls -C
如果你曾经希望能够直接复制ls显示的文件名,并将其作为命令的一部分使用而不必担心引号问题,那么你可以使用dirls -bdir等同于ls -Cb,所以从这个意义上说,你不需要dir。但是dir提供了一组选项的组合,在实践中通常很有用(尽管并不广为人知)。
为什么我从ls(甚至ls -Cb)获得彩色输出,但从dir却没有?!
大多数Ubuntu用户都有一个名为ls的别名,它运行ls --color=auto。当ls既作为别名又作为外部命令存在时,在简单的交互命令中,别名优先。
别名定义不会递归展开 - 它是通过--color=auto调用ls别名的外部ls命令。有关别名工作原理的更多信息,请参阅6.6 AliasesBash参考手册中。
当传递给lsdirvdir(以及一些其他命令,如grep)时,--color=auto只在输出到终端时使用颜色,否则不使用。
在Ubuntu中,默认情况下,用户帐户在~/.bashrc中创建了这个设置。
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

你会注意到ls的别名(alias ls='ls --color=auto')是没有被注释掉的,而dirvdir的别名则被用#注释掉了,所以它们没有生效。也就是说,虽然dir不是一个别名,但ls(但不是指向dir)。

如何让dir也能产生彩色输出?

要启用dir的彩色输出,只需编辑您家目录下的.bashrc文件,并通过删除前面的#来取消注释#alias dir='dir --color=auto'这一行。在更改后启动的shell中,dir将成为一个别名。

如果您想在当前shell中立即生效,可以将别名定义作为命令运行,或者通过运行. ~/.bashrc来加载.bashrc文件。

这可能与dir的主要目标相悖--无论输出设备如何,它都应该产生相同类型的输出。然而:

如果你觉得这个dir别名有用,那么你应该毫不犹豫地使用它。
当作为外部命令调用时,例如在脚本中或者通过运行\dircommand dir来覆盖别名时,dir仍然会产生与设备无关的输出。也就是说,将dir别名设置为dir --color=auto并不会真正破坏dir命令。

1质量很好的回答,但是可以加上目录或者简短总结一下 :) - Kevin
这是一个非常出色且富有信息的回答(+1),但我认为当你说“dir不是因为历史兼容性的原因而表现奇怪--ls才是”时,你有些过于牵强。也许你可以说GNU Coreutils中的ls之所以采取这样的行为是为了与其他发行版兼容,但不仅仅是出于历史原因;许多当前用户发现根据写入设备的不同来改变ls的输出,并继续在脚本中解析ls的输出很有用,尽管许多程序员认为那是不好的做法。 - SpinUp __ A Davis

我倾向于认为dir只是为了向后兼容而存在。
根据GNU Coreutils

dir等同于ls -C -b;也就是说,默认情况下,文件以列的形式垂直排序,并且特殊字符由反斜杠转义序列表示。

顺便说一下,默认情况下ls不会给输出着色:这是因为大多数发行版在/etc/profile.d中将ls别名为ls --color=auto。测试一下,输入unalias ls然后尝试使用ls:它将没有颜色。
来源:Renan对于“dir”和“ls”的区别回答

尽管dir不提供向后兼容性,而ls实际上是。这个答案(以及它引用的答案)确实正确陈述了这两个命令的技术差异,并解释了常见的着色差异。所以+1。 - Eliah Kagan

简短回答:没有。 dir 是与 ls 相同的源代码,ls 二进制文件默认具有 --color 功能。(1 行代码差异)

9dir 不是 ls 的别名。它们是在 /usr/bin 中表现不同的独立二进制文件,正如 Rinzwind答案 中所描述的那样。你可以通过别名来实现此操作,但这 不是 它的实现方式。所有使用 GNU Coreutils 的系统都会出现单独的 dirls 二进制文件。如果你需要证明,请运行 cmp /bin/ls /bin/dir - Eliah Kagan
3一段时间以前,它是一个别名,你只需输入alias就可以在别名列表中看到它。现在为dir编译了一个新的二进制文件。你可以使用以下命令下载其代码:git clone git://git.sv.gnu.org/coreutils。 在ls-dir.c中只修改了一行代码:int ls_mode = LS_MULTI_COL;。从技术上讲,它不是一个别名,但实际上它是带有不同默认选项的LS(只是一行代码)。 - Paco Valdez
1是的,dirls,但默认选项不同。在使用GNU Coreutils的发行版中,dirls一直是独立的二进制文件。一些发行版可能也定义了一个名为dir的别名(定义与现有命令同名的别名很常见)。但它们是独立的可执行文件。区分shell别名(根本不是一个文件)和具有类似源代码的独立可执行文件,并不是一种迂腐的区别。在Ubuntu中说dirls的别名既错误又误导。 - Eliah Kagan
1是的,我同意你的看法。但在这种情况下,不是相似的源代码,而是相同的源代码。如果我们说别名只是在alias中列出的任何内容,那当然不是别名。 - Paco Valdez
3这不是相同的源代码。正如你所说,“更改了一行源代码。”即使它是相同的源代码,它仍然不是一个别名。在类Unix系统中有很多东西与别名相似,但对于新手来说(对于经验丰富的用户来说也是令人沮丧的),将它们称为别名会造成极大的困惑。符号链接、硬链接、相同文件、相似文件、包装脚本、隐藏可执行文件的shell内置命令以及同步文件(例如使用UbuntuOne)在很多方面都类似于别名,但它们并不是别名。 - Eliah Kagan

当你有疑问时,可以比较一下type lstype dir(参见ls和la的区别)。
$ type dir
dir is aliased to `ls -l'

$ type ls
ls is aliased to `_ls'

$ type _ls
_ls is a function
_ls ()
{
    local IFS=' ';
    command ls $LS_OPTIONS ${1+"$@"}
}
$ echo command ls $LS_OPTIONS ${1+"$@"}
command ls -N --color=tty -T 0

区别在于对ls的不同选项,对我来说,--color=tty是最明显的,你的系统可能会有所不同。


3这根本不像是默认的Ubuntu用户配置。我认为我使用过的任何Ubuntu系统都没有将ls作为名为_ls的函数的别名,甚至没有在.bashrc中作为注释行出现过。然而,根据这个对话这个文件(从那里链接过来)以及我(或许错误的)记忆上次使用openSUSE的时候,它似乎是(至少某些版本的)openSuSE的默认设置。 - Eliah Kagan
2@EliahKagan:你猜对了,我正在使用OpenSuse!所以正如我所说的,结果可能会有所不同,但方法应该是正确的。 - user2394284