0

i have a simple script

wget -O file.zip www.site.com/asdqwdkjhasd.zip
unzip file.zip

and i call the script

./script.sh

now my problem is if zip file is corrupt then it outputs

  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.

how can i detect this text in script? If the output of the program contains the string "End-of-central-directory signature not found." then do something.

sometimes the downloaded zip is corrupt so it has to be redownloaded. How can i check if the output is "End-of-central-directory signature not found." and if so redownload i.e execute wget and again unzip. In other words how to loop until download and extract succeeds?

How can i achieve this in bash scripting?

I appreciate any help! Thanks!

UPDATE:

Sorry i have made a slight change to the problem. This is the actual problem i am trying to solve. Thanks for any feedbacks!

8
  • 2
    If unzip is well-written, the error will be reflected in exit status, not just output. Thus, you'll be able to use if unzip "$1"; then echo "unzip succeeded"; else echo "unzip failed"; fi, which is the best-practice approach. Checking for a specific string is fragile: It can fail if a future version of the program changes the message's text, if the user has a different language/locale and thus a different translation table; etc. Commented Feb 4, 2018 at 5:26
  • ...if you want to check not just for failure but for a specific failure, encourage the program's author to use a distinct exit status for that failure. (See man rsync for an example fo this being done well -- every major failure mode has a distinct, well-documented exit status). Commented Feb 4, 2018 at 5:34
  • @CharlesDuffy: Why don't you answer in an answer, but as a comment? However - about duplicate: Output of a command is not the same as an error message. Commented Feb 4, 2018 at 5:39
  • @userunknown, I flagged two duplicates here: One that speaks to comparing stdout (since that's what the OP literally asked), and a second one that speaks to comparing stderr (since that's what the OP actually needs). Between them, I believe we've got everything covered. Commented Feb 4, 2018 at 5:41
  • @userunknown, ...and, well, you know as well as I did why I'm not adding an answer: This is a duplicate, and adding an answer would fall afoul of site rules as described in How to Answer -- specifically the section "Answer well-asked questions", specifically the bullet point regarding questions which "have already been asked and answered many times before". Commented Feb 4, 2018 at 5:42

1 Answer 1

1

It's possible, but you normally don't.

You can pick the exit code of the last command, 0 is 0 Errors, every other value indicates some kind of error, application specific or just a general error. With $? you get the exit code from the last command, but you have to use it immediately after the command in question.

((3 < 1)) ; err=$?; echo $err
1
((3 > 1)) ; err=$?; echo $err
0

Error messages often depend on LOCALE settings:

erg=$(LC_ALL=C ls nosuchsamplefile 2>&1)
echo "$erg"
ls: cannot access 'nosuchsamplefile': No such file or directory

erg=$(ls nosuchsamplefile 2>&1)
echo $erg
ls: Zugriff auf 'nosuchsamplefile' nicht möglich: Datei oder Verzeichnis nicht gefunden

Comparing words can fail and is inherently insecure. Even by setting the command to a specific setting can't prevent updates from changing the wording and surely, the user had set his Locale to some different value for a reason.

However, 2 > &1 redirects the error stream to the output, which is the default for the screen, but on capturing, it makes a difference. As long as you just script for yourself and in ad hoc situations, approaches can be useful, which don't scale with multiple users and when to be maintained over years.

Sign up to request clarification or add additional context in comments.

15 Comments

a && b || c is an antipattern, because it changes whether c is run based not just on the exit status of a but also on the exit status of b. Best practice is to teach people to write it out: if a; then b; else c; fi. This is BashPitfalls #22.
Ok, how can 'echo file found' fail? What would your if block in such a case produce?
Also, echo "$erg", not echo $erg -- without the quotes string-splitting and glob expansion take place, so if it were ls ' * ' 2>&1 for which we'd captured an error, then unquoted echo $erg would be replacing that * with a list of filenames. This is BashPitfalls #14.
An echo can fail if the file handle is closed, or if the write fails due to a problem with whatever stdout is connected to. I/O failures are things that exist. More to the point, though, if you teach a practice, people can be expected to assume it's safe to leverage more widely unless it's taught with explicit caveats ("only safe for use in conditions X/Y/Z").
sorry for the update. i have changed the problem a bit. this is the exact problem i am trying to solve.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.