88

I've been trying to find the difference between using the dir and ls commands in terminal. I know ls is the traditional UNIX method of viewing the files in a directory, and that dir is the windows command prompt equivalent, but both commands work in terminal.

If I type in dir, it displays the files and folders in the directory, and if I type ls, it does the same, except with content highlighting. Both commands accept options (i.e. ls -a and dir -a both return all files and folders and hidden files.

So does anyone know what the difference is and why both dir and ls are used?

4
  • 8
    dir --color ;)
    – Rinzwind
    Feb 13, 2012 at 18:22
  • 3
    just wanted to say I'm surprised at the amount of response this question has received. I guess I was not the only one wondering about this :)
    – BretD
    Feb 24, 2012 at 3:25
  • 3
    Commands from ancient times always drag the older nerds out of the woodwork ;)
    – Rinzwind
    Feb 24, 2012 at 8:03

5 Answers 5

82

dir and ls are part of coreutils and dir is almost the same as ls, just with different default options.

The GNU Core Utilities are the basic file, shell and text manipulation utilities of the GNU operating system. These are the core utilities which are expected to exist on every operating system.

info dir says:

dir is equivalent to ls -C -b; that is, by default files are listed in columns, sorted vertically, and special characters are represented by backslash escape sequences.

Oh and there is also vdir! info vdir says:

vdir is equivalent to ls -l -b; that is, by default files are listed in long format and special characters are represented by backslash escape sequences.

Most likely dir exists for backwards compatibility or due to historical reasons.

4
  • I was thinking that it was probably just an alias of the other. I assumed the reasoning was to make windows users feel more at home lol Thank you for the thorough answer!
    – BretD
    Feb 13, 2012 at 19:16
  • 4
    type alias dir to see what it actually is. type alias to see all aliases.
    – user606723
    Feb 13, 2012 at 19:38
  • 2
    @user606723 , 'alias dir' doesn't show in 11.10 (at least not for me). I believe 'alias' only shows local user alias settings, not system wide.
    – James
    Feb 14, 2012 at 23:19
  • type type dir to see what it is (an alias, a command, a bash function...)
    – ychaouche
    Mar 23, 2017 at 14:20
72

The Relationship Between ls and dir

ls and dir are separate programs that behave similarly. As explained and referenced below, the purpose of dir is to provide a command like ls whose output does not vary depending on whether or not it is going to a terminal. To achieve this helpfully, dir must format its output in a way that is reasonable and useful both for viewing in a terminal and for writing to a file or pipe.

There are two common misconceptions about dir:

  • Many people believe dir is an alias of ls, but that is not the case. Neither command is an alias of the other, and by default in Ubuntu, dir is not an alias at all. ls and dir are provided by separate, non-identical executables.
  • Many people believe dir exists for obscure historical reasons or to provide compatibility with some standard or some other OS. That is not the case either. ls behaves the way it does for compatibilty. dir, which doesn't have to be compatible because it's not a standard Unix command, behaves in an alternate way that the developers consider valuable in its own right and possibly even preferable.

OK, but exactly how do ls and dir differ?

Both ls and dir list the contents of directories. Two specific differences in their default behaviors distinguish them.

  1. When its standard output is a terminal, ls lists filenames in vertically sorted columns (like ls -C). When its standard output is not a terminal (for example, a file or pipe), ls lists filenames one per line (like ls -1).

    Whether or not its standard output is a terminal, dir lists filenames in vertically sorted columns (like ls -C).

    For both ls and dir, these defaults may be overridden by the --format= flag and by the -1, -C, -m, and -x flags, which abbreviate particular --format= options. See 10.1.4 General output formatting in the GNU coreutils reference manual for details.

  2. When its standard output is a terminal and a filename to be listed contains control characters, ls prints ? instead of each control character (like ls -q). When its standard output is not a terminal, ls prints control characters as-is (like ls --show-control-chars).

    Whether or not its standard output is a terminal, when dir encounters a control character or any other character that would be interpreted specially if entered into a shell, it prints backslash sequences for the characters. This includes even relatively common characters like spaces. For example, dir will list an entry called Documents backups as Documents\ backups. This is like ls -b.

    For both ls and dir, these defaults may be overridden by the flags listed in 10.1.7 Formatting the file names in the GNU coreutils reference manual. This includes -b, -q, --quoting-style=, and some others.

Sources: ls invocation and dir invocation, in the GNU coreutils reference manual.

Why have dir?

The rationale for a separate dir utility is given in 4.5 Standards for Interfaces Generally of the GNU coding standards. I recommend reading that whole section to understand the developers' reasoning, but here are the highlights as applicable to ls/dir:

Please don’t make the behavior of a utility depend on the name used to invoke it....

Instead, use a run time option or a compilation switch or both to select among the alternate behaviors....

Likewise, please don’t make the behavior of a command-line program depend on the type of output device....

Compatibility requires certain programs to depend on the type of output device. It would be disastrous if ls or sh did not do so in the way all users expect. In some of these cases, we supplement the program with a preferred alternate version that does not depend on the output device type. For example, we provide a dir program much like ls except that its default output format is always multi-column format.

The GNU Project considers it undesirable, from a technical perspective, for a utility to produce different output depending on what kind of device it is writing to (at least in the utility's default configuration). For some utilities, including ls, device-dependent output is necessary for compatibility and so it works the way users expect. Some users do also specifically prefer this device-dependent behavior.

While ls could not reasonably be written to behave device independently, a separate dir utility was created to achieve this. Thus dir is not the utility that behaves strangely for reasons of historical compatibility--ls is.

To see how ls, dir, and the related vdir utility are implemented in the coreutils source code without needless code duplication, see ls-dir.c, ls-ls.c, ls-vdir.c, ls.h, and ls.c.

Is dir really useful?

If you've ever wished ls produced multi-column output even when you piped it to less (ls | less) or redirected it to a file (ls > out.txt), you can use dir or ls -C.

If you've ever wished you could directly copy a filename shown by ls and use it as part of a command without worrying about quoting, you can use dir or ls -b.

dir is equivalent to ls -Cb, so in that sense you don't need dir. But dir provides a combination of options that in practice is often useful (though not widely known about).

Why do I get colorized output from ls (even ls -Cb) but not dir?!

Most Ubuntu users have an alias called ls which runs ls --color=auto. When ls exists both as an alias and an external command, the alias takes precedence in simple, interactive commands.

Alias definitions aren't expanded recursively--it's the external ls command that the ls alias is calling with --color=auto. See 6.6 Aliases in the Bash reference manual for more information on how aliases work.

When passed to ls, dir, or vdir (and some other commands, like grep), --color=auto uses color when its output is a terminal, but not otherwise.

By default in Ubuntu, user accounts are created with this in ~/.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

You'll notice the ls alias (alias ls='ls --color=auto') is uncommented, while those for dir and vdir are commented out with # so they take no effect. That is, while dir is not an alias, ls is (but not to dir).

How do I make dir produce colored output, too?

To enable colored output with dir, simply edit .bashrc in your home directory and uncomment the #alias dir='dir --color=auto' line by removing the leading #. In shells started after the change, dir will be an alias.

If you want the change in the current shell, you can run the alias definition as a command, or you can source .bashrc by running . ~/.bashrc.

This arguably goes against the main point of dir--that it should produce the same sort of output regardless of the output device. However:

  • If you find it useful to make this dir alias, you should certainly do so.
  • When called as an external command, for example in scripts or if you override the alias by running \dir or command dir, dir will still produce device-independent output. This is to say that aliasing dir to dir --color=auto does not really break dir.
2
  • 1
    Quality answer, but could use a ToC or TL;DR; :)
    – Kevin
    Dec 9, 2016 at 13:36
  • This is an excellent, very informative answer (+1), but I think you're over-reaching when you say "dir is not the utility that behaves strangely for reasons of historical compatibility--ls is." Perhaps you could say that ls from GNU Coreutils behaves the way it does is for compatibility with other distributions, but not just historically; many current users find it useful for ls to change its output depending on the device it's writing to, and continue to parse the output of ls in scripts, despite the fact that many programmers consider that to be poor form. Jan 9 at 16:00
5

I would be inclined to think that dir is there just for backwards compatibility.

From GNU Coreutils:

dir is equivalent to ls -C -b; that is, by default files are listed in columns, sorted vertically, and special characters are represented by backslash escape sequences.

By the way, ls doesn't colorize the output by default: this is because most distros alias ls to ls --color=auto in /etc/profile.d. For a test, type unalias ls then try ls: it will be colorless.

Source: Renan's answer to What's the difference between “dir” and “ls”?

1
3

Short Answer : None, dir is the same source code than ls, ls binary have --color by default. (1 line of code diff)

5
  • 9
    dir is not an alias of ls. They are separate binaries in /usr/bin that behave differently, as described in Rinzwind's answer. You could achieve this with aliases, but that is not how it is achieved. Separate dir and ls binaries appear on all systems that use GNU Coreutils. If you need proof, run cmp /bin/ls /bin/dir. May 28, 2012 at 23:16
  • 3
    some time ago it was an alias and you could see it listed in the alias list just by typing alias, now a new binary is compiled for dir. You can download its code with: git clone git://git.sv.gnu.org/coreutils. Only one line of code is changed in ls-dir.c and is this: int ls_mode = LS_MULTI_COL;. Technically is not an alias, but practically it is LS but with different default options(1 line of code). May 29, 2012 at 15:09
  • 1
    Yes, dir is ls but with different default options. dir and ls have always been separate binaries in distributions that use GNU Coreutils. Some distributions may, or may have, also defined an alias called dir (defining aliases that are the same name as an existing command is pretty common). But they are separate executables. To distinguish between a shell alias (which is not a file at all) and a separate executable with similar source code, is not a pedantic distinction. It is both false and misleading to say that dir is an alias of ls in Ubuntu. May 29, 2012 at 15:32
  • 1
    Yes, I agree with you, but in this case, is not similar source code, is the same source code. If we say that an alias is just anything listed in alias then of course is not an alias. May 29, 2012 at 15:50
  • 3
    It is not the same source code. As you said, "one line of source is changed." And if it were the same source then it would still not be an alias. There are lots of things in a Unix-like system that are similar to aliases but which would be vastly confusing to novices (and exasperating to experienced users) to call aliases. Symbolic links, hard links, identical files, similar files, wrapper scripts, shell builtins hiding executables, and synced files (e.g. with UbuntuOne) are all similar to aliases in significant ways, but they aren't aliases. May 29, 2012 at 15:55
2

When in doubt, compare type ls vs type dir (see also Difference between ls and 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

The difference boils down to different options to ls, in my case --color=tty would be the most visible, your system may differ.

2
  • 3
    This doesn't seem like a default Ubuntu user configuration at all. I don't think any of the Ubuntu systems I've used have have had ls as an alias for a function called _ls -- not even as a commented-out line in .bashrc. It does seem like the default for (at least some versions of) openSuSE, though, judging by this conversation, this file (linked from there), and my (admittedly perhaps wrong) memory of when I last used openSUSE. Dec 29, 2016 at 0:58
  • 2
    @EliahKagan: You guessed it, I'm using OpenSuse! So as I said, the result will differ, but the method should be all right. Jan 9, 2017 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.