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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
You just need to create a list of glob matching files, separated by space:
for file in .* *; do echo "$file"; done
Edit
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
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0