views:

249

answers:

7

I want to iterate over each line in the output of ls -l /some/dir/* Right now I'm trying: for x in ls -l $1; do echo $x done, however this iterates over each element in the line seperately, so i get

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:07
File1

-r--r-----
1
ivanevf
eng
1074
Apr
22
13:17
File2

I want to iterate over each line as a whole, though.

How do I do that?

Thanks.

+1  A: 

It depends what you want to do with each line. awk is a useful utility for this type of processing. Example:

 ls -l | awk '{print $9, $5}'

.. on my system prints the name and size of each item in the directory.

Adam
+2  A: 

Never ever ever ever iterate over the output of ls. Get the list of files with a glob, then use stat to look at each file's properties.

Ignacio Vazquez-Abrams
True enough, but a statement like this helps no one unless you explain why it is bad. Then at least the reader can judge for themselves. Something like "You should not rely on the output of ls. For example, it may break when there are no files, or when there are large numbers of files. The output is also implementation-specific and may change."
ire_and_curses
@ire_and_curses: I figured that the asker already found one of the failure modes, so I wasn't terribly worried about explaining why.
Ignacio Vazquez-Abrams
I am somewhat of a linux noob, so I'm not sure what's wrong with iterating over the output of ls. Good to know about globs, though. Thanks!
Ivan
+1  A: 
#!/bin/bash

for x in "$(ls -l $1)"; do 
   echo "$x"
done
ire_and_curses
You probably meant to say: `for x in "$(ls -l $1)"; ...`
glenn jackman
@glenn jackman: Yes, thanks.
ire_and_curses
+1  A: 

The read(1) utility along with output redirection of the ls(1) command will do what you want.

Steve Emmerson
+1  A: 

As already mentioned, awk is the right tool for this. If you don't want to use awk, instead of parsing output of "ls -l" line by line, you could iterate over all files and do an "ls -l" for each individual file like this:

for x in * ; do echo `ls -ld $x` ; done
Axel
+1  A: 

Set IFS to newline, like this:

IFS='
'
for x in `ls -l $1`; do echo $x; done

Put a sub-shell around it if you don't want to set IFS permanently:

(IFS='
'
for x in `ls -l $1`; do echo $x; done)

Or use while | read instead:

ls -l $1 | while read x; do echo $x; done
Randy Proctor
+1 for "| while read"
Sean
A: 

You can also try the find command. If you only want files in the current directory:

find . -d 1 -prune -ls

Run a command on each of them?

find . -d 1 -prune -exec echo {} \;

Count lines, but only in files?

find . -d 1 -prune -type f -exec wc -l {} \;

David Koski