5

How can I check if a file is an archive and then extract it with 7z? I understand that I could check it by file command but it won't work in scripts because of its output. I can't predict what type of archive it could be. I just want to do something like:

Can I extract it by 7z?
If yes, extract,
if not, go further

by bash sript.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Michał
  • 53
  • 1
  • 5
  • Do you only care about 7z archives? – Jeff Schaller Mar 03 '18 at 14:04
  • @JeffSchaller The `7z` utility can cope with many archive formats including most common ones (if all the necessary plugins are installed). – Gilles 'SO- stop being evil' Mar 03 '18 at 16:14
  • Why do you care whether the file is an archive? That is, why not just try to extract and ignore (or log) failures? – minnmass Mar 03 '18 at 22:32
  • 4
    Why are you so against using the `file` command? – roaima Mar 03 '18 at 22:36
  • @roaima I am against because as far as I know, it returns 0 on success, but $? does not say if it is an extractable file or maybe a just common text file, all that information is in stdout, am I right? – Michał Mar 04 '18 at 12:55
  • 1
    The `file` command doesn't know what you're looking for (it's not an "is it _this_ type of file?" but rather a "what type of file is it?". So exit status can at best only report whether or not it could identify the file. – roaima Mar 04 '18 at 17:55
  • Why was it closed as unclear? It is a very clear question. I vote to reopen. – peterh Mar 06 '18 at 19:17

3 Answers3

11
filename=/tmp/foo.gz

if 7z t $filename; then
    7z e $filename
else
    echo $filename not an archive.
fi
Hunter.S.Thompson
  • 8,839
  • 7
  • 26
  • 41
  • 1
    Why even `7z t`? Why not just `7z filename && exit` and then do whatever else. – Kusalananda Mar 03 '18 at 14:01
  • `if 7z t $filename; then` will return 0 if it's a valid archive, so the extract will not happen, you need swap the commands between _else_ and _then_. – αғsнιη Mar 03 '18 at 14:21
  • 6
    @αғsнιη An exit code of 0 means "success" or "true" in the shell (confusing, I know), so it's the right way round in the answer. – Timo Mar 03 '18 at 14:25
  • On Fedora command `7z t $filename` extract archive immediately, or return value different from 0 if it wasn't an archive, isn't It like your snipped extract archive twice? – Michał Mar 03 '18 at 14:38
  • 1
    @Kusalananda If the file is an archive but its extraction fails, your proposal would fall back to the non-archive behavior instead of propagating the error. – Gilles 'SO- stop being evil' Mar 03 '18 at 16:14
  • @Gilles I addressed that in my own answer. – Kusalananda Mar 03 '18 at 20:42
8

The 7z utility returns a non-zero exit code if the operation it performs fails. You can use this fact to try to extract the archive and then do something else if that fails:

if ! 7z e filename 2>/dev/null; then
    # do something else
fi

or, depending on what else you want to do, or not do,

if 7z e filename 2>/dev/null; then
    exit
fi

# do something else

which may be shortened to

7z e filename 2>/dev/null && exit

# do something else

You could obviously wrap this in

if 7z t filename; then

fi

and catch a failure of extraction (due to not enough disk space or whatever other error might occur during extraction) separately from a failure of determining that this is indeed a 7z archive.

The full code may look like

if 7z t filename 2>/dev/null; then
    if 7z e filename 2>/dev/null; then
        echo 'All is good, archive extracted' >&2
    else
        echo 'Archive failed to extract' >&2
    fi
else
    echo '7z failed to process the file' >&2
fi
Kusalananda
  • 320,670
  • 36
  • 633
  • 936
  • `'File is not a proper 7z archive'` is misleading. NT executables, for example, are not 7z archives. – wizzwizz4 Mar 04 '18 at 12:21
  • @wizzwizz4 Could you explain a bit more please? I know nothing about "NT executables". If `7z t` fails, then it is not a proper 7z archive. I chose the word "proper" since it could still be a _corrupt_ 7z archive. – Kusalananda Mar 04 '18 at 12:23
  • The program 7zip can extract Windows NT executable files. Iirc `7z t consent.exe` will return `0`. It's also the case with `.zip`, `.rar` etc.. Your text is confusing. – wizzwizz4 Mar 04 '18 at 12:27
  • @wizzwizz4 Well, in that case NT executables _are_ 7z archives. What would you propose otherwise? How would you distinguish "real 7z archives" from "files that 7z can extract"? Would that even make sense to the questioner? – Kusalananda Mar 04 '18 at 12:32
  • The term "7z archive" usually refers to archives in the 7z format, like zip archive refers to ZIP files. – wizzwizz4 Mar 04 '18 at 12:33
  • @wizzwizz4 What do you think the person in the question would want to do with an unknown file? Would they want to try to extract it? If they would, then would this be a confusing script to run? If the response from the script say "this is not a 7z archive", would they be confused? If it says "archive extracted", would they be confused? – Kusalananda Mar 04 '18 at 12:39
  • Maybe something like `'7z says file is not an archive'`? – wizzwizz4 Mar 04 '18 at 12:41
6

If 7z t <archive> returns 0, then the file was a valid archive.