Reputation: 673
I'm trying to iterate over each file in a directory. Here's my code so far.
while read inputline
do
input="$inputline"
echo "you entered $input";
if [ -d "${input}" ]
then
echo "Good Job, it's a directory!"
for d in $input
do
echo "This is $d in directory."
done
exit
my output is always just one line
this is $input directory.
why isn't this code working? what am I doing wrong?
Cool. When I echo it prints out
$input/file
Why does it do that? Shouldn't it just print out the file without the directory prefix?
Upvotes: 5
Views: 8055
Reputation: 11357
You would think that looping over files would be easy, right? But this is full of pitfalls in bash.
Using globs is the WORST. Trust me, don't do it
for x in *; do # <--- bad for many reasons
echo the file name is $x
done
Using find is better, for instance.
for x in `find . -maxdepth 1 -type f`; do # <-- assume no filename has spaces
echo the file name is $x
done
find
has a lot of options to filter results by name, by date, by owner... whatever. It is very powerful.
However using a for-find
FAILS if the filename contains spaces. To fix that use...
while read x; do
echo the file name is $x
done < <(find . -maxdepth 1 -type f)
Or if you don't like that weird done
syntax, instead you can use:
result=`find . -maxdepth 1 -type f`
while read x; do
echo the file name is $x
done <<< $result
However, what if the filename contains a linefeed?! Can that happen? Yes it can happen, but it is extremely rare. So if you are PARANOID you can do:
while read -r -d '' x; do
echo the file name is $x
done < <(find . -maxdepth 1 -type f -print0)
In my opinion the extra mess is not worth it, so I don't recommend it. People who put linefeeds in filenames deserve to feel pain.
Upvotes: -1
Reputation: 146073
If you want to simplify it somewhat and get rid of the directory check, you could just write it to work on files and directories, perhaps something like:
read inputline
ls "$inputline" | while read f; do
echo Found "$f"
done
Upvotes: 2