Ubuntu – Problem with spaces in file names

command line

I want to do something repeatedly on a list of files. The files in questions have spaces in their names:

david@david: ls -l
total 32
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha
-rw-rw-r-- 1 david david  0 Mai  8 11:55 haha~
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (3rd copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (4th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (5th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (6th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (7th copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (another copy)
-rw-rw-r-- 1 david david 13 Mai  8 11:55 haha (copy)

Now I want to stat each of these files:

david@david: echo '
for file in $(ls)
do
stat $file
done' | bash

(I use echo and a pipe in order to write multi-line commands.)

When I do that, it works correctly on those files that do not have any spaces in their names. But the others…

stat: cannot stat ‘(another’: No such file or directory
stat: cannot stat ‘copy)’: No such file or directory

Changing $(ls) to "$(ls)" or $file to "$file" does not work. What can I do?

Edit:

echo '
for files in *
do
stat "$files"
done' | bash

does the trick! As I'm new to bash, I want to keep things as simple as possible – so nothing with trying to escape spaces, or using xargs or the solution with read -r, although they solve the problem.

As some have asked: Yes, using this instead of stat * is weird. But I just wanted to find a general way to apply the same command on a bunch of file names in bash, using a for loop. So stat could stand for gzip, gpg or rm.

Best Answer

The multiple quote from the echo ' is complicating the thing.

You can just use:

for f in *; do stat -- "$f"; done

But also

stat -- * 

...and if you want to collect the files and then apply the command (why?) you can go with (but be careful with file containing new lines...(1))

for f in *; do echo "$f"; done | xargs stat --

...and if you want hidden files too, just use * .* as a pattern, but then remember that . and .. will be in the set.

As an aside, you shouldn't parse ls output.


(1) but if you have file names with newlines, you somewhat deserve it... ;-)