CLI tool
xvoland/Extract avatar
xvoland/Extract

Extract is a shell function that maps an extension to the right unpacker

Bash/Zsh function for extract: .zip, .rar, .bz2, .gz, .zlib, .tar, .tbz2, .tgz, .Z, .7z, .xz, .exe, .tar.bz2, .tar.gz, .tar.xz, etc.

525 stars85 forksShellMIT

At a glance

What is it?
Extract is a Bash and Zsh function that takes a file name, looks at the extension and calls the right unpacker, covering everything from zip and tar through to appimage, epub and the comic book archive formats. It also reads from standard input, so an archive can be piped in without ever landing on disk.
Who is it for?
Adopt Extract if you extract archives often enough that remembering which tool handles which extension has become friction, since the whole point is removing that lookup. Skip it if your archive needs are covered by tar and unzip, and if you cannot install extra unpackers, since each format depends on a separate program being present.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A case statement with a long arm

The project describes itself as a Bash and Zsh function for extract, and the description is a list of formats: .zip, .rar, .bz2, .gz, .zlib, .tar, .tbz2, .tgz, .Z, .7z, .xz, .exe, .tar.bz2, .tar.gz, .tar.xz, and more.

The longer list in the introduction is worth reading because it shows what the project is actually for. Alongside the formats everybody knows are .arj, .cab, .chm, .deb, .dmg, .iso, .lzh, .msi, .rpm, .udf, .wim and .xar, and then the comic book archive formats .cbr, .cbz, .cb7, .cbt and .cba, and the container and package formats .cpio, .apk and .appimage, and then .zpaq, .arc, .ciso, .zst, .tar.zst, .vhd, .tar.lz4, .lzma, .tar.br and .epub.

The reasoning for that breadth is stated in one sentence: extract utilizes free unpackers to ensure support for even the most obscure and outdated file types.

That is the whole design. The function is not an archiver. It is a dispatcher that maps an extension to an existing command, and the formats it supports are exactly the formats you can get an unpacker for. The most obscure entry on the list, .tar.br, is Brotli-compressed tar, which is why it needs its own case alongside the more usual ones.

The implementation is described plainly. It is a Bash function called extract that takes one or more arguments, each of which represents a file or path that needs to be extracted. If no arguments are provided, the function displays usage instructions. The function uses a case statement to determine the appropriate extraction method for each file type, and then calls the corresponding command. If the file is not recognized as a valid archive, the function displays an error message and returns an error code of 1.

That is a small program. There is no dependency manager, no plugin system, no configuration file. It is a case statement and a list of command names.

The IFS handling, which is the part worth reading

There is one detail in the description that deserves more attention than it gets, and it is the kind of thing that separates a careful script from a casual one.

Before running the function, the value of the Internal Field Separator (IFS) is saved so that it can be restored at the end of the function. This is done to prevent unwanted word splitting and filename expansion when processing file paths.

This is the correct handling of a shell function that takes file names as arguments, and the reason is a classic one. The internal field separator is what the shell uses to split an unquoted expansion into separate words. If a script changes it and does not restore it, every later command in your shell session inherits the change, and things break in ways that are very hard to trace.

The failure mode when IFS is wrong is specific and nasty. A file name with a space in it becomes two arguments, and the script tries to extract a file that does not exist. A filename with a glob character in it can be expanded by the shell against the current directory, so a file called archive[1].tar.gz might turn into whatever archive1.tar.gz happens to be, or into nothing if no match exists. Both of those look like the script is broken rather than like the shell state was corrupted.

Saving and restoring it is a two-line fix and it is the difference between a function that is safe to source into your shell profile and one that quietly breaks other things later in the session.

The rest of the description is worth repeating for what it says about the interface. The function takes one or more arguments, so you can extract several archives in one command, and with no arguments at all it prints usage instructions rather than doing nothing. That is a small thing, but a command that responds to being called with no arguments is a command that tells you what it expects, and it is one of the differences between a tool and a script.

Reading an archive from a pipe

The feature that separates this from a plain alias is the standard input support, and it is explained properly.

Extract supports extracting archives from standard input, which the documentation says is perfect for use in pipelines. To do this, use a dash as the file name followed by the archive extension, so that extract knows how to handle the input.

bash
cat archive.zip | extract - .zip

The reason the extension is still needed is the same reason the dispatcher exists. The extension is what selects the unpacker, and standard input carries no file name and therefore no extension. So you supply the format separately and the function has everything it needs.

The examples given cover the three cases you would actually want:

bash
cat file.gz | extract - gz
bash
curl -sL https://example.com/file.tar.gz | extract - tar.gz
bash
wget -qO- https://example.com/file.tar.xz | extract - tar.xz

The first is a local file piped in, the second is a download piped straight into the extractor, and the third is the same with wget.

The second and third are the interesting ones in practice. A remote tarball can be fetched and unpacked in one step, with nothing written to disk except the extracted contents. On a slow connection or with a large archive that is a real saving, and it removes the download-then-extract-then-delete dance that otherwise fills your temporary directory.

There is a subtlety in the multi-part extensions. The second example passes tar-gz as the extension, not gz, because the archive is a gzipped tarball and the right unpacker is tar with the decompression flag. The third passes tar-xz. So the extension argument is not always a single suffix, and the function has to handle the compound forms as well as the simple ones.

Installing it, and the four routes

There are four ways to install it and they cover different levels of commitment.

The macOS section says to add the appropriate code into your ~/.bash_profile file, or to add the command into that file, into your ~/.zshrc, or into a ~/.functions file. And then the two commands that make it available:

bash
export PATH=<path_to_file>/extract.sh:$PATH
bash
source <path_to_file>/extract.sh

So the function can either be added to your path as an executable script or sourced into your shell as a function. The difference matters for people who care about startup time, since a sourced function has to be parsed by every new shell, while a script on your path is only read when you run it. And it matters for people who want to override it later, since a sourced function can be replaced in the current session.

The third route is a one-line install:

bash
curl -L -o install_extract.sh https://raw.githubusercontent.com/xvoland/Extract/master/install_extract.sh && bash install_extract.sh && rm install_extract.sh

That downloads the installer, runs it and removes it. It is the shortest path and also the one that asks the most trust, since you are running a script you have not read, fetched over the network, that modifies your shell configuration files.

The fourth is the manual route, and the documentation walks through it step by step. Download the code:

bash
git clone https://github.com/xvoland/Extract.git
cd Extract

Make the script executable:

bash
chmod +x install_extract.sh

And run it:

bash
./install_extract.sh

There is also a second installer:

bash
./install_extract_func.sh

The two installers are for the two installation styles, the script on your path and the sourced function, and having both is a sensible accommodation of the difference described above.

On Ubuntu and other Unix systems the instruction is simpler: copy and paste the function into your ~/.bashrc file.

The repository itself is small. There is extract.sh, which is the function itself, the two installer scripts, a .gitmessage file for the commit template, the LICENSE and the README. The script is the product.

What it depends on, and where this fits

The important practical point about Extract is that it does not implement any decompression itself. It calls the standard unpackers, which means the formats it can handle are the formats whose tools you have installed.

On a Linux machine that usually means tar and gzip are present, and possibly bzip2, xz and unzip depending on the distribution. On macOS the set is smaller out of the box, and the documentation's insistence on Mac support is partly about the shell function rather than about the unpackers.

So the formats on the long list are a ceiling rather than a floor. The function will happily accept an .arj file and then fail because no arj tool is installed. That is a reasonable design, because the alternative would be bundling every unpacker, and it is worth knowing before you conclude the tool is broken.

The comparison with the alternatives is straightforward. The built-in archive tools are fine for the two or three formats you actually use. The problem this solves is that the mapping from format to command is not something most people memorise, and looking it up costs a search each time. A single command that takes the file name and works it out removes a small but recurring tax.

The comparison with a general-purpose archiver tool such as 7-Zip or a file-roller style GUI is different in kind. Those tools have their own format support, their own command line interfaces and their own opinions. This is a shell function that stays out of the way and uses the tools you already have.

The repository is MIT licensed, copyright 2013 by Vitalii Tereshchuk, and the last push was on 2026-10-07. The lack of GitHub releases is consistent with a project whose distribution mechanism is the installer script rather than a release artefact.

What to check before you rely on it is the set of unpackers on your machine, and the two compound extensions in the stdin mode, since tar-gz and tar-xz are the ones you will hit first with a remote download. Beyond that, the function is small enough to read in a minute, which is the best argument for using something this simple.

Editorial conclusion

Adopt Extract if you extract archives often enough that remembering which tool handles which extension has become friction, since the whole point is removing that lookup. Skip it if your archive needs are covered by tar and unzip, and if you cannot install extra unpackers, since each format depends on a separate program being present. Verify first which of the underlying unpackers are installed on your machine, because the function dispatches to them rather than implementing them.

Frequently asked questions

What is the Extract shell function and how does it work?

It is a Bash and Zsh function that takes one or more file paths and extracts each one. It uses a case statement on the file extension to decide which extraction method to use, and then calls the corresponding command, for example unzip for a ZIP archive. If a file is not recognised as a valid archive it prints an error message and returns an error code of 1, and with no arguments at all it prints usage instructions.

How do I install the Extract command?

On macOS you can add it to ~/.bash_profile, ~/.zshrc or a ~/.functions file, either by putting the directory on your PATH with `export PATH=<path_to_file>/extract.sh:$PATH` or by sourcing it with `source <path_to_file>/extract.sh`. On Ubuntu and other Unix systems you copy and paste the function into ~/.bashrc. There is also a one-line installer that downloads and runs install_extract.sh, and a manual route where you clone the repository, make the script executable and run the installer.

Can Extract unpack an archive that is piped in from standard input?

Yes. You use a dash as the file name followed by the archive extension, so that the function knows which unpacker to use, for example `cat archive.zip | extract - .zip` or `curl -sL https://example.com/file.tar.gz | extract - tar.gz`. For compound formats you pass the whole extension, so a gzipped tarball is given as tar-gz and an xz-compressed tarball as tar-xz.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. xvoland/Extract on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xvoland-extract.svg)](https://hysenlabs.com/projects/xvoland-extract)

Was this useful?