1

I did this script

#!/bin/bash

liste=`ls -l`
for i in $liste
do
    echo $i
done

The problem is I want the script displays each result line by line, but it displays word by word :

I have :

my_name
etud 
4096
Oct
8
10:13

and I want to have :

my_name etud 4096 Oct 8 10:13

The final aim of the script is to analyze each line ; it is the reason I want to be able to recover the entire line. Maybe the list is not the best solution but I don't know how to recover the lines.

federem
  • 299
  • 1
  • 6
  • 17
  • 2
    possible duplicate of [How do you process the output of a command in the shell line-by-line?](http://stackoverflow.com/questions/3113005/how-do-you-process-the-output-of-a-command-in-the-shell-line-by-line) – Mark Reed Oct 10 '13 at 16:47
  • @federem Why don't you tell us what _specific_ information you want from the line? Timestamp? Size? There are better ways to get those things, not involving `ls`. – Charles Duffy Oct 11 '13 at 00:18

5 Answers5

1

To start, we'll assume that none of your filenames ever contain newlines:

ls -l | IFS= while read -r line; do
    echo "$line"
    # Do whatever else you want with $line
done

If your filenames could contain newlines, things get tricky. In this case, it's better (although slower) to use stat to retrieve the desired metadata from each file individually. Consult man stat for details about how your local variety of stat works, as it is unfortunately not very standardized.

for f in *; do
    line=$(stat -c "%U %n %s %y" "$f")  # One possibility
    # Work with $line as if it came from ls -l
done
chepner
  • 497,756
  • 71
  • 530
  • 681
  • True. If you have to run a new process for each file anyway, though, the control over the output that `stat` allows may be more convenient. (But yeah, I simply overlooked that you could call `ls` for each file.) – chepner Oct 10 '13 at 20:51
0

You can replace

echo $i

with

echo -n "$i "

echo -n outputs to console without newline.

Fabrice Jammes
  • 2,275
  • 1
  • 26
  • 39
  • 1
    `echo -n` is not POSIX standard. `printf` is the safe, portable approach. – Charles Duffy Oct 10 '13 at 17:00
  • @Charles Duffy, it is defined in IEEE Std 1003.1-2001 POSIX. – Jim Black Oct 10 '13 at 18:32
  • @JimBlack Only as an XSI extension. – Charles Duffy Oct 10 '13 at 21:48
  • @JimBlack quote: "The System V echo **does not support any options,** but allows escape sequences within its operands, as described for XSI implementations in the OPERANDS section." Another quote: "It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted." – Charles Duffy Oct 10 '13 at 21:49
0

Another to do it with a while loop and without a pipe:

#!/bin/bash

while read line
do
    echo "line: $line"
done < <(ls -l)
Labynocle
  • 4,062
  • 7
  • 22
  • 24
  • This is correct (except for using `read` without `-r` -- thus having escape sequences interpreted -- and leaving `$IFS` at defaults -- and thus having trailing whitespace stripped), if the goal is to demonstrate reading from a stream. It's incorrect, if the goal is to demonstrate reading a list of files (some people really do think that `ls` is the right way to do this!). It would be good for an answer to be more clear. – Charles Duffy Oct 10 '13 at 16:59
0

First, I hope that you aren't genuinely using ls in your real code, but only using it as an example. If you want a list of files, ls is the wrong tool; see http://mywiki.wooledge.org/ParsingLs for details.

Second, modern versions of bash have a builtin called readarray.

Try this:

readarray -t my_array < <(ls -l)
for entry in "${my_array[@]}"; do
  read -a pieces <<<"$entry"
  printf '<%s> ' "${pieces[@]}"; echo
done

First, it creates an array (called my_array) with all the output from the command being run.

Then, for each line in that output, it creates an array called pieces, and emits each piece with arrow brackets around them.

If you want to read a line at a time, rather than reading the entire file at once, see http://mywiki.wooledge.org/BashFAQ/001 ("How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?")

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • 1
    `<(ls -l)` will fail under the same circumstances as `ls -l | while read...`. – chepner Oct 10 '13 at 17:23
  • @chepner If your meaning is `ls`-specific, I don't believe I ever implied anything to the contrary -- see the first paragraph of my answer. (That said, unless you don't consider losing any process-local state relating to the content you've read "failing", I can't agree with the accuracy of the objection in the general, non-ls-specific case) – Charles Duffy Oct 10 '13 at 21:46
0

Joinning the previous answers with the need to store the list of files in a variable. You can do this

echo -n "$list"|while read -r lin
do
 echo $lin
done
FeLocci
  • 1
  • 1