Reputation:
I want to use command substitution in a for
loop in my bash script like this:
for file in `ls`; do
echo "$file"
tar xzvf "$file"
done
The problem is upon extracting each file and in the next iteration, ls would be executed again so the for
loop iterate over new collection. I decided to capture ls
output before starting the loop and use that in loop:
files=`ls`
for file in ${files}; do
echo "$file"
tar xzvf "$file"
done
But it seems instead of running ls
and store the result in $files
, shell just replaces ${files}
with ls
and I'm at the same point as I was in first code example.
How can I force shell to run ls
command in files=ls
part of code?
Update
I'm on my Ubuntu 16.04 laptop:
$ uname -a
Linux laptop 4.4.0-131-generic #157-Ubuntu SMP Thu Jul 12 15:51:36 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
and GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
There is a folder in my home named test
with two simple compressed files plus my script:
test
├── a.tar.gz
├── b.tar.gz
└── script.sh
script.sh
content:
#!/usr/bin/env bash
files=`ls`
for file in ${files}; do
echo "$file"
tar xzvf "$file"
done
And here is the output of bash -x script.sh
from inside of test
folder:
++ ls
+ files='a.tar.gz
b.tar.gz
script.sh'
+ for file in '${files}'
+ echo a.tar.gz
a.tar.gz
+ tar xzvf a.tar.gz
a
+ for file in '${files}'
+ echo b.tar.gz
b.tar.gz
+ tar xzvf b.tar.gz
b
+ for file in '${files}'
+ echo script.sh
script.sh
+ tar xzvf script.sh
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
And finally bash script.sh
(after deleting extracted files manually) output:
a.tar.gz
a
b.tar.gz
b
script.sh
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
Thanks for your help and patience.
Upvotes: 2
Views: 4153
Reputation:
It seems I was confused by tar
command output because inside a.tar.gz
there is a file named a
and the same for b.tar.gz
.
Changing the code as following solved the problem:
files=`ls`
for file in ${files}; do
echo "$file"
tar xzvf "$file" &> /dev/null
done
Upvotes: 0
Reputation: 42999
Your script shouldn't be processing a file more than once and it wouldn't pick up the results of tar x
in the same execution, unless it is rerun. However, there are a few issues there:
So, it can be written in a better way to address the above issues:
for zipfile in *.tar.gz; do
printf '%s\n' "Processing file '$zipfile'"
tar xzvf "$zipfile" && mv "$zipfile" "$zipfile.done"
if (($? == 0)); then
printf '%s\n' "$zipfile: success"
else
printf '%s\n' "$zipfile: failure"
fi
done
Upvotes: 4