If you have ever ran ls on a directory whose contents don't fit on screen, you may have tried to list only a part of it by passing a wildcard to the command. For example, if you were only interested in all directory entries starting with an f, you might have tried ls f*. But did that do what you expected? Most likely not if any of those matching entries was a directory. In that case, you might have thought that ls was actually recursing into those directories.

Let's consider a directory with two entries: a file and a directory. It may look like:
$ ls -l
total 12K
drwxr-xr-x 2 jmmv jmmv 4096 Dec 19 15:18 foodir
-rw-r--r-- 1 jmmv jmmv 0 Dec 19 15:18 foofile
The ls command above was executed inside our directory, without arguments, hence it listed the current directory's contents. However, if we pass a wildcard we get more results than expected:
$ ls -l *
-rw-r--r-- 1 jmmv jmmv 0 Dec 19 15:18 foofile

total 4K
-rw-r--r-- 1 jmmv jmmv 0 Dec 19 15:19 anotherfile
What happened in the previous command is that the shell expanded the wildcard; that is, ls never saw the special character itself. In fact, the above was internally converted to ls -l foofile foodir and this is what was actually passed to the ls utility during its execution. With this in mind, it is easy to see why you got the contents of the sample directory too: you explicitly (although somewhat "hidden") asked ls to show them.

How to avoid that? Use ls's -d option, which tells it to list the directory entries themselves, not their contents:
$ ls -l -d *
drwxr-xr-x 2 jmmv jmmv 4096 Dec 19 15:19 foodir
-rw-r--r-- 1 jmmv jmmv 0 Dec 19 15:18 foofile
Update (21st Dec): Fixed the first command shown as noted by Hubert Feyrer.

Go to posts index

Comments from the original Blogger-hosted post: