Shell – Differing outputs of the commands “ls .*” and “ls *.”

lsshellwildcards

The command

    ls .*

when run gives as output the following :

  • All the files in the current directory starting with a . (hidden files)
  • All the files in the hidden directories present in the current directory
  • All the files in the current directory
  • All the files in the parent directory

Why does the command

    ls *.

not display :

  • All the files in the current directory
  • All the files in the parent directory

Reason I am thinking so is : The regular expression *. should match both . and .. So ls should be run on both and thus the output which I am expecting should be displayed

Best Answer

It's because * doesn't match files starting with a . by default. Consider the following directory:

$ ls -la 
total 8404
drwxrwxrwx   2 terdon terdon 8105984 Dec 31 13:14 .
drwxr-xr-x 153 terdon terdon  491520 Dec 30 22:32 ..
-rw-r--r--   1 terdon terdon       0 Dec 31 13:14 .dotfile
-rw-r--r--   1 terdon terdon       0 Dec 31 13:14 file1
-rw-r--r--   1 terdon terdon       0 Dec 31 13:14 file2
-rw-r--r--   1 terdon terdon       0 Dec 31 13:14 file3.

Let's see what each of the globs you used expands to:

$ echo .*
. .. .dotfile

$ echo *.
file3.

$ echo *
file1 file2 file3.

As you can see, the * does not include files or directories starting with . so both ./ and ../ are ignored. The same thing happens with your ls example. In bash, you can change this with the dotglob parameter, which will cause * to expand to dotfiles as well (but not to . or .., those are still ignored):

$ shopt -s dotglob
$ echo *
.dotfile

Other shells behave differently. For example zsh also ignores the . and .. when using .*:

% echo .*
.dotfile
Related Question