Reputation: 1305
This is a simple formatting question but the answer escapes me.
I have a bash script to find certain files with a wildcard, print to file, and send in an email. I need to ls -lrt $var*
but I can't get the output to print cleanly line by line like you see on the screen. I'm looking for this in the output file:
-rw-rw-r-- 1 user user 14173 Nov 30 06:39 20171129_file1.txt.gz<br>
-rw-rw-r-- 1 user user 30954 Nov 30 06:39 20171129_file2.txt.gz<br>
-rw-rw-r-- 1 user user 95933 Nov 30 07:01 20171129_file3.txt.gz<br>
-rw-rw-r-- 1 user user 399507 Nov 30 08:43 20171129_file4.txt.gz<br>
I tried this:
for f in `ls -ltr $var*`; do
echo $f >> /tmp/mailtext
done
But the file output has a new line for every field:
-rw-rw-r--
1
user
user
133119
Dec
1
07:06
20171130_filename.txt.gz
etc......
And then I tried this, with printf, which doesn't send a new line like echo, but the four files are all jumbled together.
for f in `ls -ltr $var*`; do
printf "x $f" >> /tmp/mailtext
done
which produces the output all on one line:
x -rw-rw-r--x 1x userx userx 13318x Decx 1x 07:06x 20171130_filename1.txt.gzx -rw-rw-r--x 1x userx userx 30793x Decx 1x 07:06x 20171130_filename2.txt.gzx -rw-rw-r--x 1x userx userx 99811x Decx 1x 08:00x 20171130_filename3.txt.gzx -rw-rw-r--x 1x userx userx 41363x Decx 1x 08:10x 20171130_filename4.txt.gz
Of course I tried printf "x $f\n" but then it looked like the one in the first try.
So, any ideas how to do this simple formatting? Thank you!
Upvotes: 0
Views: 1655
Reputation: 3801
As you realised with those 2 tests, doing:
for i in `some command` ; do
...
done
makes some command's output be parsed and word-splitted according to the $IFS, and then i takes each of those values, one by one. In your case, it will be splitted around spaces, so each words is read one by one.
What you need is simply to redirect the command's output in a file, just do:
ls -lrt "$var"* > somefile
Notice that I add quotes around a "$var" (it's a good practice, in almost all cases), and that I leave the *
outside those double-quotes so that the shell still interpret's it as a globbing request.
If you wanted instead to print the result line by line (with some pause in between), you can do the following:
for file in "$var"* ; do
ls -lrt "$file" # mandatory double-quotes
sleep 1 # will sleep 1 second before looping
done | tee somefile # shows both on your screen AND sends to "somefile"
or any variation thereof.
Notice here that I do not parse the output of ls (for exemple: the broken way: ls -lrt "$var"* | whil IFS= read -r line; do ... ; done
: will not work well if any filename contains a newline, and there are other bad side effects as well).
Instead I use directly the correct way: the for loop let's the shell put the relevant filename inside the $file
var, one by one .
See : http://mywiki.wooledge.org/BashPitfalls (entry 1) for a good explanation.
Upvotes: 1