This question already has an answer here:

I need to iterate through every file inside a directory. One common way I saw was using the for loop that begins with for file in *; do. However, I realized that it does not include hidden files (files that begin with a "."). The other obvious way is then do something like

for file in `ls -a`; do

However, iterating over ls is a bad idea because spaces in file names mess everything up. What would be the proper way to iterate through a directory and also get all the hidden files?

marked as duplicate by Gilles shell-script Oct 16 '14 at 23:44

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.


You just need to create a list of glob matching files, separated by space:

for file in .* *; do echo "$file"; done


The above one can rewrite in different form using brace expansion

 for file in {.*,*}; do echo "$file"; done

or even shorter: for file in {.,}*; do echo "$file"; done

Adding the path for selected files:

 for file in /path/{..?,.[!.],}*; do echo "$file"; done

Adding path for selected files:

 for file in /path/{.,}*; do echo "$file"; done

If you want to be sophisticated and remove from the list usually unneeded . and .. just change {.,}* to {..?,.[!.],}*.

For completeness it is worth to mention that one can also set dotglob to match dot-files with pure *.

shopt -s dotglob

In zsh one needs additionally set nullglob to prevent the error in case of no-matches:

setopt nullglob

or, alternatively add glob qualifier N to the pattern:

for file in /path/{.,}*(N); do echo "$file"; done
  • Thanks a lot! So if I want to iterate through any directory, I just put the directory name in front of each of the items right? like for file in dir/.* dir/*; do – stakSmashr Oct 16 '14 at 20:46
  • 2
    It's not so easy. .* matches . and .. (except in zsh). * stays * if there is no matching file. shopt -s gotglob is only in bash. – Gilles Oct 16 '14 at 23:23
  • I am getting zsh: no matches found: .* when I run the command(s) in this answer. Why would this happen? ls on the directory shows the files. – Niyaz Oct 10 '17 at 18:57
  • @Niyaz that's because zsh return error if some pattern no matches. To prevent that run setopt nullglob which will turn off this feature globally, or add qualifier (N) after the glob star, i.e.: for file in /path/{.,}*(N); do echo "$file"; done. – jimmij Oct 10 '17 at 22:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.