Just wanted to share this, because I spent all morning figuring it out for myself. As someone that's used macOS a lot recently one of the features I really appreciate is Safari's ability to automatically extract archives when you open them. Granted that's about the only feature I appreciate about Safari, but I'll give credit where credit is due.
Having recently reinstalled Arch on my home workstation this is one the the features that I've really missed, so this morning I decided to add the feature myself.
Starting off I knew I'd most likely need to write a script and somehow associate the mime-types of the various archives I want to open with that script. Keep in mind that these instructions are known to work on GNOME and require the zsh shell. Different types of archives also require different programs to open them.
Here are the 2 files you're going to need. I'll explain them a bit further down.
First is extract.zsh
(place this in ~/.local/bin
):
# Copyright 2021 Chris Watson (watzon) | |
# | |
# Use of this source code is governed by an MIT-style | |
# license that can be found in the LICENSE file or at | |
# https://opensource.org/licenses/MIT. | |
# Most of this is taken verbatim from the oh-my-zsh "extract" plugin, just with a few changes. | |
# Please see: https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/extract | |
# ~/.local/bin/extract.zsh | |
extract() { | |
setopt localoptions noautopushd | |
if (( $# == 0 )); then | |
cat >&2 <<'EOF' | |
Usage: extract [-option] [file ...] | |
Options: | |
-r, --remove Remove archive after unpacking. | |
EOF | |
fi | |
local remove_archive=1 | |
if [[ "$1" == "-r" ]] || [[ "$1" == "--remove" ]]; then | |
remove_archive=0 | |
shift | |
fi | |
local pwd="$PWD" | |
while (( $# > 0 )); do | |
if [[ ! -f "$1" ]]; then | |
echo "extract: '$1' is not a valid file" >&2 | |
shift | |
continue | |
fi | |
local success=0 | |
local extract_dir="${1:a:r}" | |
local file="$1" full_path="${1:A}" | |
case "${file:l}" in | |
(*.tar.gz|*.tgz) (( $+commands[pigz] )) && { pigz -dc "$file" | tar xv } || tar zxvf --overwrite "$file" ;; | |
(*.tar.bz2|*.tbz|*.tbz2) tar xvjf --overwrite "$file" ;; | |
(*.tar.xz|*.txz) | |
tar --xz --help &> /dev/null \ | |
&& tar --xz -xvf --overwrite "$file" \ | |
|| xzcat "$file" | tar xvf --overwrite - ;; | |
(*.tar.zma|*.tlz) | |
tar --lzma --help &> /dev/null \ | |
&& tar --lzma -xvf --overwrite "$file" \ | |
|| lzcat "$file" | tar xvf --overwrite - ;; | |
(*.tar.zst|*.tzst) | |
tar --zstd --help &> /dev/null \ | |
&& tar --zstd -xvf --overwrite "$file" \ | |
|| zstdcat "$file" | tar xvf --overwrite - ;; | |
(*.tar) tar xvf --overwrite "$file" ;; | |
(*.tar.lz) (( $+commands[lzip] )) && tar xvf --overwrite "$file" ;; | |
(*.tar.lz4) lz4 -c -f -d "$file" | tar xvf --overwrite - ;; | |
(*.tar.lrz) (( $+commands[lrzuntar] )) && lrzuntar -f "$file" ;; | |
(*.gz) (( $+commands[pigz] )) && pigz -dk "$file" || gunzip -f -k "$file" ;; | |
(*.bz2) bunzip2 -f "$file" ;; | |
(*.xz) unxz -f "$file" ;; | |
(*.lrz) (( $+commands[lrunzip] )) && lrunzip -f "$file" ;; | |
(*.lz4) lz4 -f -d "$file" ;; | |
(*.lzma) unlzma -f "$file" ;; | |
(*.z) uncompress -f "$file" ;; | |
(*.zip|*.war|*.jar|*.ear|*.sublime-package|*.ipa|*.ipsw|*.xpi|*.apk|*.aar|*.whl) unzip -o "$file" -d "$extract_dir" ;; | |
(*.rar) unrar x -o+ -ad "$file" ;; | |
(*.rpm) | |
command mkdir -p "$extract_dir" && builtin cd -q "$extract_dir" \ | |
&& rpm2cpio "$full_path" | cpio --quiet -id ;; | |
(*.7z) 7za x -aoa "$file" ;; | |
(*.deb) | |
command mkdir -p "$extract_dir/control" "$extract_dir/data" | |
builtin cd -q "$extract_dir"; ar vx "$full_path" > /dev/null | |
builtin cd -q control; extract ../control.tar.* | |
builtin cd -q ../data; extract ../data.tar.* | |
builtin cd -q ..; command rm *.tar.* debian-binary ;; | |
(*.zst) unzstd -f "$file" ;; | |
(*.cab) cabextract -d "$extract_dir" "$file" ;; | |
(*.cpio) cpio -idmvF "$file" ;; | |
(*) | |
echo "extract: '$file' cannot be extracted" >&2 | |
success=1 ;; | |
esac | |
(( success = success > 0 ? success : $? )) | |
(( success == 0 && remove_archive == 0 )) && rm "$full_path" | |
shift | |
# Go back to original working directory in case we ran cd previously | |
builtin cd -q "$pwd" | |
done | |
} | |
extract $1 | |
xdg-open ${1:a:r} |
And then the desktop file (place this in ~/.local/share/applications
:
[Desktop Entry] | |
Comment=Extract archives regardless of type | |
Terminal=true | |
Name=extract | |
Exec=/usr/bin/env zsh ~/.local/bin/extract.zsh %f | |
Type=Application | |
Icon=/usr/share/icons/gnome/48x48/apps/gnome-settings-theme.png | |
Encoding=UTF-8 | |
Hidden=false | |
NoDisplay=false | |
Categories=AudioVideo;Player;Recorder; | |
MimeType=application/gzip;application/x-7z-compressed;application/x-7z-compressed-tar;application/x-arj;application/x-bzip;application/x-bzip-compressed-tar;application/x-bzip1;application/x-bzip1-compressed-tar;application/x-cabinet;application/x-cd-image;application/x-compress;application/x-compressed-tar;application/x-cpio;application/x-deb;application/x-gtar;application/x-gzip;application/x-gzpostscript;application/x-lha;application/x-lhz;application/x-lzma;application/x-lzma-compressed-tar;application/x-ms-wim;application/x-rar;application/x-rar-compressed;application/x-rpm;application/x-tar;application/x-xz;application/x-xz-compressed-tar;application/x-zip;application/x-zip-compressed;application/zip;application/vnd.ms-cab-compressed; |
How does it work?
Honestly it's super simple, and makes use of some existing code from Oh-My-ZSH. extract.zsh
checks the extension of the file you're trying to extract and matches it with the correct program for opening that file. This script was meant to be used as a zsh plugin, but I repurposed it. In doing so I needed to change the output directory (initially files were being extracted to my user's home directory) and make it automatically overwrite existing directories since we wanted this process to be automatic.
The .desktop
file allows the script to be registered as the default program for a given mime-type. All you have to do is open one archive with a given extension using the extract
menu option and that's it, extract is now the default program for opening those archives.
Now for the little bit of setup:
Any archive formats you want to have automatically extract need to be opened with extract so that the default for that archive type can be changed. To do this (on GNOME) right click an archive, select "Open With Other Application", click "Find New Applications" at the bottom of the dialog, and then find extract
in the list. If you don't see it you may need to log out and then log back in again.
That's really it. Now download an archive and try opening it directly from the downloads menu in your browser. The archive should be extracted and then the directory automatically opened.
Top comments (0)