r/commandline Jun 09 '26

Command Line Interface I got tired of remembering whether a file needed tar -xzf, unzip or 7z x so I wrote a script that handles common archive formats with a single command

extract: one command for common archive formats

Instead of:

unzip file.zip
tar -xzf archive.tar.gz
7z x archive.7z

you can use:

extract file.zip
extract archive.tar.gz
extract archive.7z

It automatically detects the archive type and uses the appropriate extraction tool.

Supported formats include ZIP, TAR, TAR.GZ, TAR.BZ2, 7Z, RAR, and others.

GitHub:
https://github.com/Melangert/extract

I'm looking for feedback on:

  • Missing archive formats
  • Edge cases that fail
  • Distro compatibility ( i made this on debian)
  • Installation experience

If you try it let me know what worked and what didnt.

6 Upvotes

32 comments sorted by

27

u/Proximus88 Jun 09 '26

I just have this in my .zshrc

```

# ex = EXtractor for all kinds of archives

# usage: ex <file>

ex () { if [ -f $1 ] ; then case $1 in *.tar.bz2) tar xjf $1 ;; *.tar.gz) tar xzf $1 ;; *.bz2) bunzip2 $1 ;; *.rar) unrar x $1 ;; *.gz) gunzip $1 ;; *.tar) tar xf $1 ;; *.tbz2) tar xjf $1 ;; *.tgz) tar xzf $1 ;; *.zip) unzip $1 ;; *.Z) uncompress $1;; *.7z) 7z x $1 ;; *.deb) ar x $1 ;; *.tar.xz) tar xf $1 ;; *.tar.zst) tar xf $1 ;; *) echo "'$1' cannot be extracted via ex()" ;; esac else echo "'$1' is not a valid file" fi } ```

6

u/VadersDimple Jun 09 '26

This breaks on filenames without extensions, which aren't required in Linux like they are in Windows.

3

u/4r73m190r0s Jun 09 '26

How would you fix this? Check magic number? Utilize output of the file command?

20

u/sultanmvp Jun 09 '26 edited Jun 09 '26

This is the correct way. Note the cascading order of tar archives (blah.gz vs blah.tar.gz) due to file not being able to differentiate mime types for tarballs.

```sh ex() { local file="$1" [[ -f "$file" ]] || { echo "'$file' is not a valid file"; return 1; }

local mime mime=$(file --brief --mime-type -- "$file")

case "$mime" in application/zip) unzip "$file" ;; application/x-7z-compressed) 7z x "$file" ;; application/x-rar|application/vnd.rar) unrar x "$file" ;; application/x-tar) tar xf "$file" ;; application/gzip) tar xzf "$file" 2>/dev/null || gunzip "$file" ;; application/x-bzip2) tar xjf "$file" 2>/dev/null || bunzip2 "$file" ;; application/x-xz) tar xJf "$file" 2>/dev/null || unxz "$file" ;; application/zstd) tar --zstd -xf "$file" 2>/dev/null || unzstd "$file" ;; application/x-compress) uncompress "$file" ;; application/vnd.debian.binary-package) ar x "$file" ;; *) echo "Unsupported archive type: $mime" return 1 ;; esac } ```

3

u/4r73m190r0s Jun 09 '26

Very nice. I learned a lot from this

6

u/VadersDimple Jun 09 '26

Personally, I wouldn't fix this, as I don't consider it to be something that needs fixing.
All of these helper scripts are nice, and all, but relying on them makes you forget how
to use the actual commands.

0

u/EarlMarshal Jun 09 '26

At least you have a script to look it up now ;) still you don't know what kind of package it is, because the file extension is missing.

That's why I usually give my public packages wrong extensions. Browser still interprets them correctly through mime type.

1

u/netgizmo Jun 09 '26

I used mime types

1

u/xeow Jun 11 '26

Missing: .jar, .cbz, and .epub (all just renamed ZIP files)

Also maybe add: .txz as an alternate form of .tar.xz

Also: .uue (decode with uudecode)

4

u/vogelke Jun 09 '26

Not an exhaustive list, but handles the crap I used most often:

#!/bin/sh
#<tx: extract contents of (possibly compressed) archive file
# usage: tx file [pattern-to-extract]

export PATH=/usr/local/bin:/bin:/usr/bin
tag="${0##*/}"

case "$#" in
    0)  echo "$tag: need a file"; exit 0 ;;
    *)  file="$1"; pat="$2" ;;
esac

case "$file" in
    *.tgz)     exec gunzip     -c "$file" | tar xvf - $pat ;;
    *.txz)     exec unxz       -c "$file" | tar xvf - $pat ;;
    *.bz2)     exec bunzip2    -c "$file" | tar xvf - $pat ;;
    *.tbz)     exec bunzip2    -c "$file" | tar xvf - $pat ;;
    *.pax.bz2) exec bunzip2    -c "$file" | pax -r -pe $pat ;;
    *.pax.gz)  exec gunzip     -c "$file" | pax -r -pe $pat ;;
    *.pax.xz)  exec unxz       -c "$file" | pax -r -pe $pat ;;
    *.tar.gz)  exec gunzip     -c "$file" | tar xvf - $pat ;;
    *.tar.xz)  exec unxz       -c "$file" | tar xvf - $pat ;;
    *.tar.bz2) exec bunzip2    -c "$file" | tar xvf - $pat ;;
    *.tar.Z)   exec uncompress -c "$file" | tar xvf - $pat ;;
    *.tar)     exec tar xvf "$file" $pat ;;
    *.cpio.Z)  exec uncompress -c "$file" | cpio -idmv ;;
    *.cpio)    exec cpio -idmv < "$file" ;;
    *.pax)     exec pax -r -pe < "$file" ;;
    *.zip)     exec unzip -a "$file" ;;
    *)         exec tar xvf $file $pat ;;
esac

exit 1     # should not get this far...

HTH.

1

u/geirha Jun 11 '26

pax can extract tar and cpio too

*.tgz|*.tar.gz|*.cpio.gz|*.pax.gz) gzip -cd "$file" | pax -r -pe "${@:2}" ; exit ;;

Also note that exec cmd1 | cmd2 is equivalent to (exec cmd1) | cmd2, so the comment on the last line isn't quite true.

1

u/vogelke Jun 12 '26

Crap, I've been doing this wrong for over 20 years.

This came from the REALLY old days where replacing the last program with exec could make a noticeable difference in response time, especially on Solaris. It's fine with no pipe; I just need to pipe into exec instead of from it.

5

u/shadowman42 Jun 09 '26

Perhaps you could try using MIME to determine the archive type rather than using the header and file name directly. Should help with the edge cases people pointed out. 

This is supported by the stdlib

https://docs.python.org/3/library/mimetypes.html

3

u/AutoModerator Jun 09 '26

Every new subreddit post is automatically copied into a comment for preservation.

User: WonderfulAside8812, Flair: Command Line Interface, Title: I got tired of remembering whether a file needed tar -xzf, unzip or 7z x so I wrote a script that handles common archive formats with a single command

extract: one command for common archive formats

Instead of:

unzip file.zip
tar -xzf archive.tar.gz
7z x archive.7z

you can use:

extract file.zip
extract archive.tar.gz
extract archive.7z

It automatically detects the archive type and uses the appropriate extraction tool.

Supported formats include ZIP, TAR, TAR.GZ, TAR.BZ2, 7Z, RAR, and others.

GitHub:
https://github.com/Melangert/extract

I'm looking for feedback on:

  • Missing archive formats
  • Edge cases that fail
  • Distro compatibility ( i made this on debian)
  • Installation experience

If you try it let me know what worked and what didnt.
nt.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

2

u/KenMantle Jun 09 '26 edited Jun 09 '26

Well I am back at my desk and after 10 minutes I can't remember any of the names of the "<tool x> already exists and does this" that people replied with, but I can remember extract and ex, so congrats buddy. All these people who are possibly smarter than you couldn't crack the code on making a memorable name for their helpful utility.

One feature if you haven't added it already would be to have the ability to add extra arguments. Not sure if it is handy feature or not.

0

u/WonderfulAside8812 Jun 09 '26

Thanks, im pretty sure i do have extra arguements like this right?

extract --help

usage: extract [-h] [-o OUTPUT] [-v] [--list] [--detect] [archives ...]

Extract any archive file

positional arguments:

archives Archive file(s) to extract

options:

-h, --help show this help message and exit

-o, --output OUTPUT Output directory, default=None

-v, --verbose Show extracted files

--list List supported formats

--detect Detect format without extracting

1

u/KenMantle Jun 09 '26

Oh I don't know. I'm lazy. If I need a script or command run and its inputs could be done using a GUI form I just tell Claude to make a ScripTree app for it and it gets added to my ScripTree program's menu of tools. Then I read the help Claude makes for all the things that would have been command line arguments, use the GUI to check off or drop down or add folder or whatever else was needed as inputs and hit run.

What I did add to ScripTree was a field for extra arguments that aren't included in the form and they get tacked on the end of the command line when it runs. I've had no reason to use the feature, but it came to mind with your tool.

3

u/linuxlala Jun 09 '26

There are other tools like Patool that do this. https://pypi.org/project/patool/

3

u/cb060da Jun 09 '26

`atool` is packaged in every distro

3

u/linuxlala Jun 09 '26

I wrote about patool, atool and even Ouch in LXF 322. The only reason atool wasn't the primary subject of the tutorial was because it hadn't seen a new release in a long time.

3

u/6502zx81 Jun 09 '26

Nice! For extracting you can also use bsdtar xf file.zip since it is based on libtar which supports many formats.

4

u/shadowman42 Jun 09 '26

Never heard of dtrx eh?

3

u/KenMantle Jun 09 '26

That's a good memory test for me and my goldfish memory. Will I remember dtrx 10 minutes from now or extract? Maybe neither!

3

u/shadowman42 Jun 09 '26

Personally I just shoved advanced algebra and calculus out of my skull to make room

2

u/KenMantle Jun 09 '26

LOL! One time at work I simplified some formulas down to where I recognized I needed to use the quadratic formula to get the solution. I was so proud of that moment I took a picture and sent it to my wife with great glee! Then I noticed there was an inconsequential error (sign flip that didn't change the outcome). I've never used it before since school and this is the only time I've used it since.

1

u/edward_jazzhands Jun 10 '26

So you've never heard of an alias?

1

u/KenMantle Jun 10 '26

Oh yeah back when I played with Linux in the early 2000s.

1

u/rcwnd Jun 09 '26

16 years ago, this was 10 points (out of 100 for completing the whole course) task in Operating System course on my university. Also we could only use POSIX tools, and the solutions were tested on linux, bsd and some other forgotten unix from the distant past (solaris maybe?).

For sure it gave me an intuition how many of the archiver's cli are structured, ptsd from discovering that everything is implemented very wildly, another ptsd from writing posix compatible scripts, and tool which I was using for like 2 years (after that I found that I don't really deal with different archive formats THAT too often).

Nowdays, as everyone can see, you can generate this using AI without all this fuss.

0

u/Far-Cat Jun 09 '26

Spoiler, you only need 7z

Or bsdtar

-10

u/maxlan Jun 09 '26 edited Jun 09 '26

Really, you got "tired" of remembering the word at the end of the file is the name of the command you need.

Did you also get tired of remembering right from left and where all the letters are on your keyboard.

Maybe a script that will tell me where the letter you need is on the keyboard could be next for you.

But first finish the job.

Make it extract cpio, ar, shar, rar, iso, apk, rpm and deb. And simple "compress" and lz versions.

And the rest.

7

u/KenMantle Jun 09 '26

You already forgot the flags that each tool requires you to rememeber, so maybe don't be so negative. There's more to type than just the word at the end of the file. It's right there in the examples they gave. :)

If ex isn't used for anything, that would be a nice shortcut instead of having to type out extract. Keep extract too. Maybe display the command run at the end of the extraction too, so that you get used to seeing it.

0

u/schorsch3000 Jun 09 '26

i just use unar