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!

kofhearts
  • 3,607
  • 8
  • 46
  • 79
  • 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. – Charles Duffy Feb 04 '18 at 05: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). – Charles Duffy Feb 04 '18 at 05: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. – user unknown Feb 04 '18 at 05: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. – Charles Duffy Feb 04 '18 at 05: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](https://stackoverflow.com/help/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*". – Charles Duffy Feb 04 '18 at 05:42
  • thanks for the answers. I have updated the problem. Sorry this is the exact problem i am trying to solve. – kofhearts Feb 04 '18 at 05:43
  • @kofhearts, ...btw, insofar as your goal is to check whether a zipfile is corrupt, `unzip -t` is explicitly built for the job. – Charles Duffy Feb 04 '18 at 05:44
  • @kofhearts, "how do I loop until a command succeeds" is another question that's been asked and answered several times; I'll add a few more dupes to the list. – Charles Duffy Feb 04 '18 at 05:45

1 Answers1

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.

user unknown
  • 35,537
  • 11
  • 75
  • 121
  • `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](http://mywiki.wooledge.org/BashPitfalls#cmd1_.26.26_cmd2_.7C.7C_cmd3). – Charles Duffy Feb 04 '18 at 05:31
  • Ok, how can 'echo file found' fail? What would your if block in such a case produce? – user unknown Feb 04 '18 at 05:36
  • 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](http://mywiki.wooledge.org/BashPitfalls#echo_.24foo). – Charles Duffy Feb 04 '18 at 05:36
  • 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"). – Charles Duffy Feb 04 '18 at 05:37
  • sorry for the update. i have changed the problem a bit. this is the exact problem i am trying to solve. – kofhearts Feb 04 '18 at 05:44
  • @CharlesDuffy: Yes, thank you. Using ls ' * ' wasn't what I did. Doing so, would give kofhearts however a valueable learning experience. Expanding hints beyond intended scope is not avoidable. Learning by practice is in the end the only way to experience. – user unknown Feb 04 '18 at 05:46
  • @kofhearts: And why do you believe my answer is rendered invalid by this? Did you read it? Did you test it? – user unknown Feb 04 '18 at 05:48
  • @userunknown, learning by practice can be painful. At one former employer, an ops team with many decades of experience between them lost billing data backups because someone didn't bother to quote expansions in a script handling filenames that "couldn't possibly" have characters other than hex digits... until one did (because of a buffer overflow in a 3rd-party library used by a program writing to that directory). That was a **very** expensive learning experience; learning from someone else's war story would have been far cheaper. – Charles Duffy Feb 04 '18 at 05:49
  • @CharlesDuffy: Please explain which file handle has to be closed, and how I can force such a problem to happen. Your reasoning looks very academic to me. SE is not a reference, you get hints and are self responsible for investigating further in the issue. – user unknown Feb 04 '18 at 05:54
  • @userunknown, to provide a concrete example: `exec >&-` will cause any subsequent `echo` to fail. – Charles Duffy Feb 04 '18 at 05:55
  • @userunknown, ...that said, where I'm coming from here is many years in the freenode #bash channel trying to get people to avoid bugs caused by bad habits that they picked up from the ABS (as a particularly notorious reference). It's not so much that the ABS is full of outright wrong information (though there's some), but that it's full of bad-practice examples that might be harmless *in the context where they're used to demonstrate something else*, but which are harmful when taken outside that context. – Charles Duffy Feb 04 '18 at 05:57
  • @userunknown,. ...and in #bash, we had people coming to us with problems caused by taking practices out of the examples where they were known to be safe and applying them somewhere they weren't *all the time*. Which is why we built [our own alternative to the ABS](http://mywiki.wooledge.org/BashGuide) explicitly to have something with a stronger focus on showcasing best practices and avoiding glossing over details with significant potential to bite someone down the line. – Charles Duffy Feb 04 '18 at 05:58
  • @CharlesDuffy: Sorry, I didn't teach `exec >&-`. How is that related to `ls nosuchsamplefile && echo file found || echo "no file found"`? Who should invoke that exec where? – user unknown Feb 04 '18 at 05:58
  • @userunknown, you asked for an example of a situation wherein `echo file found` could fail. I gave you one -- the scenario where stdout is a file handle that's closed, or pointing to somewhere non-writable, as created by `exec >&-`. The point isn't that you taught anyone to write `exec >&-`, the point is that you described as a flow control construct a practice that, when abused as such, can execute *both* the "then" and "else" clauses, without telling the reader that it's only safe to use in `echo`-equivalent cases. – Charles Duffy Feb 04 '18 at 05:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/164478/discussion-between-user-unknown-and-charles-duffy). – user unknown Feb 04 '18 at 06:09