The command 'ls -d' is not displaying directories. Is there a way to get 'ls' to only display directories instead of files and directories?
Solution 1
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.
Solution 2
You can usels -d */
, or ls -d .*/
for hidden directories.
Solution 3
Try this
find . -mindepth 1 -maxdepth 1 -type d
to get just directories under your current location.
Solution 4
You might also like
tree -d
which neatly lists all directories and subdirectories with a graphical depiction of the tree structure.
Solution 5
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.
Related videos on Youtube
nelaaro
Linux admin, tech enthusiast. opensource evangelist.
Updated on September 18, 2022Comments
-
nelaaro almost 2 years
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
/
directory 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?-
boehj over 12 yearslsd can be very confusing.
-
nelaaro over 12 years@jin ls -d */ works. But why do I have to "*/" to get the out put I want.
-
Jin over 12 years@nelaar
-d
doesn't mean to list directories only, it means to not list directory contents. Try typingls */
and you'll see the contents of all the directories. -
DQdlM over 12 yearsI have
ldir
alised tols -d */
in my.bashrc
to make this easier... -
Gaff over 12 yearspossible duplicate of How to list folders using bash commands?
-
DimiDak over 5 yearsls can give you tons of information but not one single flag for just showing directories...
-
-
nelaaro over 12 yearsthanks you. I realize I was not thinking about wildcard expansion correctly. You have clarified that very well for me. You have helped a lot. I can actually say I get it.
-
Random832 over 12 years"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] -
JdeBP over 12 yearsIt'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. Whereasdir /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. -
Random832 over 12 yearsRight, 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".
-
JdeBP over 12 yearsKiddo, it's not only relevant; it's the core of the problem. If you don't understand that, you don't understand one of the fundamentals of Unix. Think! Start by re-reading what I wrote and think about what race conditions and subtle scripting connotations I referred to. The race conditions are fairly well known, and the scripting connotations can be seen with a little applied thought.
-
nom-mon-ir over 11 yearsclever trick using the / !
-
Thanatos over 11 yearsRandom832 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. -
ocodo almost 11 yearsThis is going to filter out more than directories.
-
Anne van Rossum over 10 yearsAnd for only one level deep:
tree -dL 1
-
JdeBP over 10 yearsYou and Thanatos, even though I've explained it twice already, have entirely missed the point. It's not about
ls
being altered to treat directories differently, as if somehow it didn't already. We know that it can and it does. That is right there in the answer. You've both not thought about what I said to think about, including the fundamentals of Unix, which mean that there's no way for an option tols
to control shell wildcard expansion. Random832 was specifically contradicting that statement of mine, and providing as supposed proof a mechanism that doesn't actually work as claimed. -
iyrin over 9 yearsYeah this is good. Is there any case where this doesn't work?
-
mkalkov almost 9 years@Slomojo, this will filter out everything but directories. What did you mean?
-
mkalkov almost 9 yearsIt may be even better to use
find -maxdepth 1 -type d -exec ls -d {} +
to get output in the usualls
format. -
mkalkov almost 9 years@JdeBP, ad-hominem attacks ("kiddo") and arrogance (everybody except you does not know "the fundamentals of Unix") do not belong to a technical discussion. Furthermore, you're pulling a straw man when you argue that a command option cannot control wildcard expansion done by shell. Of course, it cannot! Neither Random832, nor Thanatos, nor Anne van Rossum, and not even the question itself mention wildcards in any way. The objection was that
ls --only-directories .
option could be added tols
eventually. -
Calculus Knight over 8 years+1 for providing the answer in one line. I'm guessing the accepted answer also has it, somewhere.
-
neuronet about 8 yearsAnswer is pedantic and presumptuous. Consider ls -l which lists all the stuff in the working directory. One might very reasonably expect ls -d to just list all the directories in the current directory (especially given the output of man ls, which OP quoted). The convention of showing everything in the working directory, subject to some constraint set by an option flag, is ubiquitous in bash. There is nothing weird or MSDOSish about it at all. Whatever happened to just answering the question.
-
geoO over 7 yearsYeah, you need the -l (long) so that permissions head up the line. "d" for directory. Plus you get a "long" listing of a directory entry which is nice.
-
DimiDak over 5 yearsUnfortunately you can't combine much with tree. # tree -d | grep wc -l (standard input)
-
DimiDak over 5 yearsLs could just add the "directories only" flag. With this hack "ls -d */" you have to be in the directory to see subdirectories.
-
DimiDak over 5 yearsHow can you use this in a script without being in the directory already?
-
felwithe about 3 yearsMyy expectations have nothing to do with Windows. Have a downvote. I didn't read the rest.