How to read filenames with space in between

Hi All,

I need to read filenames with space in between in a for loop
like
Integration of utility projects
Integration of hdf projects

I copied these files from a windows system and as you know windows filename has spaces in between them.

But while unix is reading the filename in a for loop it reads word by word and in the end it's futile because all the filenames has space in between.

This is the command I use to read the filenames

for i in `ls -l`

Is there a way to accomplish this. Please help me on this. :confused:

try

ls -1 | while read filename
do
  echo "$filename" 
done  

Thanks a lot.

It worked fine.

Can you please explain why is this not possible in a for loop instead of a while loop? What makes the difference.

Hi,

There is no reason that it doesn't work with for loop, try this:

for i in "`ls -1`"
do
echo "$i"
done

you could also set the internal-field-seperator to a newline, if you use bash

IFS="
"

check man bash /IFS

Notice that the solution is 'ls -1' (one, not "el"). That puts each file on it's own line. When you read it, you're assigning the whole line to a variable, not per whitespace-delimited word.

Infact you dont need an "ls -1" as such. A simple ls would do. In this case, the output of ls -1 and ls is the same. The output would be a file per line.

Not So,

default output of a simple ls is multiple column output with minimal of 2-columns and ls -1 enables single column output.

Output of single file per line is guaranteed with ls -1 only

Not so, :slight_smile:

What ls does depends on the version of ls. I am aware of two behaviors:

  1. ls defaults to one filename per line. (the original, but now rare behavior.)

  2. ls examines stdout. If it is a tty, it switches to multiple filesnames per line, otherwise it puts 1 filename per line.

Since a pipe is not a tty, "ls|cat" will always be one filename per line. Ditto with using ls in a script in the manner shown above. If you really have an ls version with a third behavior, please tell us which version of unix you are using....after verifying that it is not an alias or something like that.

I've verified all the all the claims.

1.It doesn't work with for loop

for i in "`ls -1`" considers the entire listing in one variable and goes thro' only one loop

2.changing IFS to newline doesn't work

3.And as per the last post even piping ls works.( Excellent finding :slight_smile: )

I believe in the while loop read command makes all the difference. Correct me if I am wrong.

Cheers. :o

OK, you're wrong. It's a lot of stuff. At many places, the unix shell thinks in terms of words separated by spaces. Do:
echo `ls *`
You were beaten as soon as the ls finished. The backticks made the shell collect all of the output into one large line with a space between words. Then there is no way to tell the difference between:
"foot ball"
and
"foot" and "ball"
And what if a file has twenty spaces between two words in the filename? They get compressed to just one space.

The solution Jim posted avoids backticks. It also avoids using the "for" statement which loops on words. It is more what he avoided than what he used. His solution will work for embedded spaces and trailing spaces. But it will stumble on leading spaces which are very hard to support.

just use *

for i in *
do
echo "$i"
done

Accepted Per.

But on doubt,
I verified the source code of ls from opensolaris.

I dont think the command is distinguishing itself with respect to tty or pipe ( or any other stream)