5

pwd is my home directory. ls */ -d displays the directories.

~$ ls */ -d
Blog/  Desktop/  Documents/  Downloads/  Music/  Pictures/  Public/  Templates/  Videos/

And ls -a displays all hidden directories and files. Hidden directories - .cache, .local etc.

$ ls -a
.                        .cache      .gnupg       .xsession-errors.old
..                       .config     .gtkrc-2.0   Templates
.bash_history            Desktop     .gtkrc-xfce  Pictures      .themes
.bash_logout             .linuxmint   .pki          Videos
.bashrc                  Documents   .local       .profile      .viminfo
Blog                     Downloads   .mozilla     Public        .Xauthority
Music        .ssh          .xsession-errors

But when I run ls -ad */, it won't displays any hidden directories. Anyone care to explain?

$ ls -ad */ 
Blog/  Desktop/  Documents/  Downloads/  Music/  Pictures/  Public/  Templates/  Videos/
NayabSD
  • 194

3 Answers3

16

When you run ls -a, there are no filenames on the ls command line (as seen by ls), so it determines the filenames it should list by itself. Since -a is specified, that includes showing “hidden” files.

When you run ls -d */ and ls -ad */, the shell expands */, and provides the list of filenames which ls will show. * at the start of a filename pattern doesn’t match ., so */ doesn’t include hidden files: in combination with -d, the -a has no effect here.

To see hidden directories, you can list them explicitly: ls -d -- */ .*/. In some shells, you can ask for * to match hidden files too; for example in Bash, with shopt -s dotglob (note that . and .. are not included in that case which makes it behave more like ls -A).

Also note the -- that you forgot to mark the end of options to make sure file names are not treated as options if they start with -. Also note that */ includes directories and symlinks to directories. If using zsh, you can do ls -d -- *(D/) to list directories only (including hidden ones with D), and without adding a trailing / to each file. Or *(D-/) if you do want the symlinks to directories.

Stephen Kitt
  • 434,908
14

* deliberately doesn't match hidden files or directories, because most of the time that's exactly what is wanted (as dot files and directories are generally used for configuration, not data), and you can override the default by explicitly specifying a glob starting with . if/when you need to.

If you want them to be matched by a glob, use ls -d .* (or ls -d .*/ to match only hidden directories without regular files). To match both hidden and non-hidden directories, use ls -d -- */ .*/

NOTE: as mentioned by @rexkogitans in a comment, globs like * are expanded by the shell before they are passed to a program. ls never sees a * or .* (or .*/), it sees the list of file and/or directory names that are the result of the shell expanding the glob. This is why you need to quote or escape (by prefixing with a backslash) glob characters if you want to pass them as string literals to a program.

Also note: if there are no files/dirs matching the glob then the glob is passed to the program as is, unexpanded (i.e. ls will see * as its argument). bash (and some other bourne-like shells) allow this behaviour to be over-ridden - e.g. in bash, you can use the nullglob or failglob shell options. nullglob causes it to be expanded to nothing (i.e. it is removed from the argument list), while failglob triggers an error.

cas
  • 78,579
  • 5
    I guess it should be pointed out that */ is replaced by shell globbing before command invocation. Since you have 9 unhidden directories, it is replaced by 9 respective parameters passed to ls. This behaviour differs from DOS and Windows, where the parameter */ is passed literally to the command (e.g. dir), and the command needs to perform the globbing. – rexkogitans Aug 06 '21 at 10:59
-1

The short answer, which doesn’t seem to be spelled out well anywhere, is that, in ls, -a / -A are ignored when you use -d, because -a / -A control the way ls displays (lists) the contents of directories, and -d tells it not to list the contents of directories.