I want to write a shell script that will loop through all the files in a directory and echo "put ${filename}". Can anyone point me in the right direction?
Asked
Active
Viewed 1.2e+01k times
43
-
2What have you tried? What part of the `for` statement and the `*` operator confuse you? Can you be more specific about what you know and what you don't know about the shell? – S.Lott Dec 14 '11 at 22:15
-
Just came across this -- a warning to anyone using this as a reference -- the answers do not handle filenames with spaces properly... refer to https://stackoverflow.com/questions/7039130/iterate-over-list-of-files-with-spaces for a better solution!!! – blackghost Jun 02 '17 at 15:59
6 Answers
65
For files and directories, not recursive
for filename in *; do echo "put ${filename}"; done
For files only (excludes folders), not recursive
for file in *; do
if [ -f "$file" ]; then
echo "$file"
fi
done
For a recursive solution, see Bennet Yee's answer.

ThisClark
- 14,352
- 10
- 69
- 100

Oliver Charlesworth
- 267,707
- 33
- 569
- 680
-
1If the current directory happens to be empty, this outputs "put *" rather than correctly outputting nothing. Can it be fixed? – JWWalker Apr 27 '13 at 01:47
-
1@ThisClark - Indeed it does. But I'm not sure that an answer not doing *exactly* what you want is a good reason to downvote. – Oliver Charlesworth Sep 03 '18 at 16:52
-
@ThisClark - True. But being generous to myself (!), one could argue that from a *nix perspective, a folder **is** is a file. (Possibly that's what I was thinking when I wrote the answer 7 years ago, but who knows...) – Oliver Charlesworth Sep 03 '18 at 17:07
-
What does nix even stand for? Disregarding the distinction of files from folders is not helpful. – ThisClark Sep 03 '18 at 17:38
-
-
This does not list any hidden files (i.e. those starting with ".") in bash on macOS 10.13. Is that normal? How do I get all files, including the hidden ones? – Thomas Tempelmann Apr 06 '20 at 16:00
-
1
-
What if one wants to pass the name of the directory as a variable (I posted a more precise question there: https://stackoverflow.com/questions/76021261/passing-a-string-to-a-loop-to-iterate-in-all-subdirectories-and-files) – ecjb Apr 15 '23 at 09:06
19
Recursively (including files in subdirectories)
find YOUR_DIR -type f -exec echo "put {}" \;
Non-recursively (only files in that directory)
find YOUR_DIR -maxdepth 1 -type f -exec echo "put {}" \;
Use *
instead of YOUR_DIR
to search the current directory

winklerrr
- 13,026
- 8
- 71
- 88

Bennet Yee
- 506
- 2
- 6
-
1I get the error `find 'dir': No such file or directory` when trying this. – gbmhunter Dec 19 '13 at 22:44
-
2Silly me, by dir you meant replace with the directory you want. Still, slightly confusing! – gbmhunter Dec 19 '13 at 22:45
-
1Recursively for files in the current directory, replace `dir` with `*`. – ThisClark Sep 03 '18 at 17:45
-
2What does this part do? "put {}" Especially meaning of the curly braces {} – Ayusman Jul 03 '19 at 06:25
-
use '.' for all files in the current directory instead of 'dir'. note that find will also go through the "hidden" files/directories the names of which start with a dot. – Bennet Yee Feb 18 '21 at 23:05
-
the '{}' is replaced with the path to the filesystem object identified by the conditions specified earlier. – Bennet Yee Feb 18 '21 at 23:06
-
wouldn't a pipe with `$1` be easier than the ` -exec echo .. {} `? Also, I just noticed that find isn't GNU compliant with it's options syntax. Is it not a core util? Sorry for digging up this grandad of a Q / A, but it is a popular page, and I felt that I had useful info to add (the first part, not the second. ). – Nate T Aug 21 '21 at 01:59
8
For all folders and files in the current directory
for file in *; do
echo "put $file"
done
Or, if you want to include subdirectories and files only:
find . -type f -exec echo put {} \;
If you want to include the folders themselves, take out the -type f
part.
-
1This does not list files starting with a "." in bash v3 (macOS). Is there a solution for that? – Thomas Tempelmann Apr 06 '20 at 16:01
3
If you don't have any files, then instead of printing * we can do this.
format=*.txt
for i in $format;
do
if [[ "$i" == "$format" ]]
then
echo "No Files"
else
echo "file name $i"
fi
done

Mad-D
- 4,479
- 18
- 52
- 93
1
One more alternative using ls
and sed
:
$ ls -1 <dir> | sed -e 's/^/put /'
and using ls
and xargs
:
$ ls -1 <dir> | xargs -n1 -i%f echo 'put %f'

jcollado
- 39,419
- 8
- 102
- 133
-
-
@WilliamPursell Thanks, I've updated my response. Somehow, I misunderstood and made the braces and the dollar sign part of the solution. Also, I'ved another solution with `xargs` and `echo`, but the `sed` one is still more concise. – jcollado Dec 15 '11 at 06:05
0
this will work also recursively if you have any sub directories and files inside them:
find . -type f|awk -F"/" '{print "put ",$NF}'

Vijay
- 65,327
- 90
- 227
- 319