Reputation: 51
I have a problem finding the right command to search and find a string in multiple ZIP files containing XML files on Unix.
I am able to find a search string in multiple ZIP files but haven't been successful with replacing the finding and replacing that string.
Unfortunately this isn't quite working. I'm trying to use a grep and sed command once it finds the string the unzipped file (to temp location). But I'm probably incorrect to assume that I can edit to temp?
oldAddress='<ns1:line1/>'
newAddress='<ns1:line1>somestring</ns1:line1>'
for file in *.zip; do
unzip -c "$file" | grep -q "<ns1:line1/>" | xargs -l {} sed -i 's/$oldAddress/$newAddress/g'
done
Thanks in advance.
Upvotes: 5
Views: 6960
Reputation: 28858
First, while it's tempting to use globals, bash also supports the following loop style:
while read line ; do echo $line; done < <(find . -iname 'file*zip')
Second, you can use zipgrep
to search the files, and then only unzip those who really need to unzip. This will cause two time deflation of the files. Once for greping and once for unzipping thos who really need to be unzipped. However, this will spare us the need to zip the redundant files back.
Third, you are searching 2 times, for large file or many files this will be two times slower:
grep -q "<ns1:line1/>" | xargs -l {} sed -i 's/$oldAddress/$newAddress/g'
Instead you can unzip only those matching files, and do the search and replacement in one step using only sed.
# From within a (bash) script you need to use double quotes instead of singel qoutes to expand the variable
newAddress="<ns1:line1>somestring</ns1:line1>"
oldAddress="<ns1:line1/>"
for fname in *.zip
do
zipgrep -q $oldAddress $fname;
if [ $? -eq 0 ]; then
filename="${fname%.*}"
unzip -qp $fname | sed -e 's#'$oldAddress'#'$newAddress'#g' > $filename
zip $filename.zip $filename
fi
done
Here is a for loop to create a test data:
for i in {1..4} ; do touch file$i; done
while read line ; do
echo '<ns1:line1/>' > $line;
zip $line.zip $line
rm $line
done < <(find . -iname 'file*')
Upvotes: 1