Iterating over each line of ls -l output
LinuxShellLinux Problem Overview
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 separately, 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
But I want to iterate over each line as a whole, though. How do I do that?
Linux Solutions
Solution 1 - Linux
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
One more option, which runs the while/read at the same shell level:
while read x; do echo $x; done << EOF
$(ls -l $1)
EOF
Solution 2 - Linux
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.
Solution 3 - Linux
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
Solution 4 - Linux
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 {} \;
Solution 5 - Linux
The read(1) utility along with output redirection of the ls(1) command will do what you want.
Solution 6 - Linux
So, why didn't anybody suggest just using options that eliminate the parts he doesn't want to process.
On modern Debian you just get your file with:
ls --format=single-column
Further more, you don't have to pay attention to what directory you are running it in if you use the full directory:
ls --format=single-column /root/dir/starting/point/to/target/dir/
This last command I am using the above and I get the following output:
bot@dev:~/downloaded/Daily# ls --format=single-column /home/bot/downloaded/Daily/*.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141119_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141120_IENT1.txt.gz
/home/bot/downloaded/Daily/Liq_DailyManifest_V3_US_20141121_IENT1.txt.gz