Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Is there a way to get ls to only display directories instead of files and directories

From the man page.

       -d, --directory
              list directory entries instead of contents, and do not  derefer‐
              ence symbolic links

So if I type it at the / dir. I expect to see only directories. Instead it shows "."

$ cd /
$ ls -d

I was expecting ls -d to show me this

$ ls -d
bin data home opt sbin sys var
boot dev lib media proc selinux tmp
cdrom etc lost+found mnt root srv usr

Is there a way to get ls to only display directories instead of files and directories

share|improve this question
lsd can be very confusing. – boehj Oct 10 '11 at 9:12
@jin ls -d */ works. But why do I have to "*/" to get the out put I want. – nelaar Oct 10 '11 at 9:33
@nelaar -d doesn't mean to list directories only, it means to not list directory contents. Try typing ls */ and you'll see the contents of all the directories. – Jin Oct 10 '11 at 9:45
I have ldir alised to ls -d */ in my .bashrc to make this easier... – KennyPeanuts Oct 10 '11 at 11:09
possible duplicate of How to list folders using bash commands? – 8088 Oct 11 '11 at 2:19
up vote 38 down vote accepted

Your expectations are based upon DOS Think/Windows Think and are wrong. On MS-DOS, Windows, and indeed a few other IBM/Microsoft operating systems, wildcard expansion is done by the command itself, and things like the /a option to the dir command act as attribute filters during wildcard expansion. dir expands wildcards like *, which the command interpreter passes to it as-is, and if /a is specified it applies the appropriate filters to what is returned. (On some operating systems, the attribute filters can be given to the system call for enumerating a directory and the operating system kernel, or its filesystem drivers, applies them itself.)

On Unices and on Linux, wildcard expansion is done by the shell, and is oblivious to permissions. When, in the root directory, you do

ls *

what the ls command itself receives from the shell is (something like)

ls bin home opt var boot dev tmp etc lost+found root usr

What the -d/--directory option does is turn off what normally happens next. What normally happens next is that ls looks at each of its arguments in turn, sees that they are directories, and decides to enumerate their contents. For arguments that name files, it just prints out the information for the file itself. With the -d option, directories are treated just like files. So ls prints out the information for each of the directories that is passed as its arguments, just as it would do if they were files.

So -d is not a "print only directories" option. In fact, not only is there no such option; there cannot be such an option. Wildcard expansion is done by the shell, and (in a POSIX sh at least) there's no way to tell the shell to check permission and file type bits when it expands * into a list of names. To obtain a list of the names of directories alone, it is necessary either to use the find command, as explained by ztank1013, or to use the trick that a pathname ending with a slash implies the directory entry ., as explained by Jin. (Jin's trick ends up with the ls command receiving the arguments

ls bin/ home/ opt/ var/ boot/ dev/ tmp/ etc/ lost+found/ root/ usr/

because the pattern */ is in fact matching pathnames with two components, the second being empty, and so isn't quite doing what was desired. In particular, it will treat symbolic links pointing to directories as if they were directories.)

The behaviour of ls -d without a * is a simple extension of the above. One simply has to know one more thing about ls: When it is given no arguments, it assumes a default argument of .. Now without the -d option, the aforementioned behaviour leads to the contents of the directory named by . being enumerated and the information for its contents displayed. With the -d option, the directory . is treated just as if it were a file, and its own information is displayed, rather than its contents enumerated.

share|improve this answer
"there cannot be such an option" - that's a rather strong statement - the implementation of such an option is obvious: see a non-directory argument and ignore it. What can't be implemented is the equivalent of dir /s *.txt [without resorting to quoting wildcards as for find] – Random832 Oct 10 '11 at 13:25
It's a strong and true statement for a system like Unix where wildcard expansion is divorced from entry type checking. Your hypothetical implementation is erroneous. What you describe still expands * to include the non-directories, with all of the filesystem race conditions and subtle scripting connotations that that entails. Whereas dir /a:d will, on operating systems that have this functionality in the system API, skip non-directories immediately without even returning them to application-mode code. – JdeBP Oct 10 '11 at 15:09
Right, but there's no logical reason ls can't have an option which will filter out items that were passed in as arguments. The fact that "wildcard expansion is divorced from entry type checking" is irrelevant, since this has nothing at all to do with wildcard expansion - only entry type checking, which there is no reason it cannot be done entirely within ls. If ls --color can shade them blue, ls -F can put a / after them, and ls -l can put a 'd' in the mode, then some other hypothetical option could omit them. That such an option does not exist doesn't mean it "cannot". – Random832 Oct 10 '11 at 17:15
Random832 makes a decent point: ls could have an option to filter files or directories, and this isn't mutually exclusive with having the shell do expansion. There's no race condition within ls: it can filter it as it stats the files normally. (There is already a race between the shell expansion and ls, FWIW.) I think shell expansion is only part of the reason: shell expansion (and filtering in general) is not implemented in ls because it would need to be implemented again in cp, mv, etc. Unix is a "do one thing and do it well". If you need advanced filtering, there are tools for that. – Thanatos Mar 20 '13 at 5:45
The ls -p option adds a / symbol to directories only. There is no reason not to extend the output printing capabilities with something that does only output these (rather than ls -p | grep /). – Anne van Rossum Mar 14 '14 at 9:00

You can usels -d */, or ls -d .*/ for hidden directories.

share|improve this answer
clever trick using the / ! – Mono Mar 8 '13 at 23:39
Yeah this is good. Is there any case where this doesn't work? – iyrin Feb 7 '15 at 23:11
+1 for providing the answer in one line. I'm guessing the accepted answer also has it, somewhere. – Calculus Knight Sep 28 '15 at 15:25

Try this

 find . -mindepth 1 -maxdepth 1 -type d

to get just directories under your current location.

share|improve this answer

You might also like

tree -d 

which neatly lists all directories and subdirectories with a graphical depiction of the tree structure.

share|improve this answer
And for only one level deep: tree -dL 1 – Anne van Rossum Mar 14 '14 at 9:14

If you want to see directories only with detail like ls -l (ELL) option then you can use below:

find -maxdepth 1 -type d -ls;

Above will only give you the detail like you get with the -l option.

share|improve this answer
It may be even better to use find -maxdepth 1 -type d -exec ls -d {} + to get output in the usual lsformat. – mkalkov Aug 7 '15 at 9:40

If you want to get the job done in another way, try this:

ls -l | grep ^d

Although a single tool is enough in this situation. Pipe line is always there to help you. I like the flexibility in Linux, which I wish you do.

share|improve this answer
This is going to filter out more than directories. – Slomojo Sep 1 '13 at 0:05
@Slomojo, this will filter out everything but directories. What did you mean? – mkalkov Aug 7 '15 at 9:37

I hope this will rectify your need. The below command will list only directories in a given path.

ls -F <path> | grep /


ls -F ~ | grep /
share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .