diff --git a/plugins/README.md b/plugins/README.md index 0a9baae11..174ee795f 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -37,6 +37,7 @@ By leveraging these plugins, you can streamline your workflow and tackle coding | colored-man-pages | Adds a few colors to `man` pages. | | chezmoi | Dotfile management tool enabling management of user environment configuration. | | dotnet | This plugin provides completion and useful aliases for .NET Core CLI. | +| extract | This plugin defines a function called `extract` that extracts the archive file you pass it, and it supports a wide variety of archive filetypes. | | fasd | Utility easing filesystem navigation through shortcuts and abbreviated commands. | | fzf | A command-line fuzzy finder. | | gcloud | Command-line tools for interacting with Google Cloud Platform (GCP). | diff --git a/plugins/extract/README.md b/plugins/extract/README.md new file mode 100644 index 000000000..904c17830 --- /dev/null +++ b/plugins/extract/README.md @@ -0,0 +1,67 @@ +# extract plugin + +This plugin defines a function called `extract` that extracts the archive file you pass it, and it supports a +wide variety of archive filetypes. + +This way you don't have to know what specific command extracts a file, you just do `extract ` and +the function takes care of the rest. + +To use it, add `extract` to the plugins array in your zshrc file: + +```zsh +plugins=(... extract) +``` + +## Supported file extensions + +| Extension | Description | +| :---------------- | :----------------------------------- | +| `7z` | 7zip file | +| `Z` | Z archive (LZW) | +| `apk` | Android app file | +| `aar` | Android library file | +| `bz2` | Bzip2 file | +| `cab` | Microsoft cabinet archive | +| `cpio` | Cpio archive | +| `deb` | Debian package | +| `ear` | Enterprise Application aRchive | +| `exe` | Windows executable file | +| `gz` | Gzip file | +| `ipa` | iOS app package | +| `ipsw` | iOS firmware file | +| `jar` | Java Archive | +| `lrz` | LRZ archive | +| `lz4` | LZ4 archive | +| `lzma` | LZMA archive | +| `obscpio` | cpio archive used on OBS | +| `rar` | WinRAR archive | +| `rpm` | RPM package | +| `sublime-package` | Sublime Text package | +| `tar` | Tarball | +| `tar.bz2` | Tarball with bzip2 compression | +| `tar.gz` | Tarball with gzip compression | +| `tar.lrz` | Tarball with lrzip compression | +| `tar.lz` | Tarball with lzip compression | +| `tar.lz4` | Tarball with lz4 compression | +| `tar.xz` | Tarball with lzma2 compression | +| `tar.zma` | Tarball with lzma compression | +| `tar.zst` | Tarball with zstd compression | +| `tbz` | Tarball with bzip compression | +| `tbz2` | Tarball with bzip2 compression | +| `tgz` | Tarball with gzip compression | +| `tlz` | Tarball with lzma compression | +| `txz` | Tarball with lzma2 compression | +| `tzst` | Tarball with zstd compression | +| `vsix` | VS Code extension zip file | +| `war` | Web Application archive (Java-based) | +| `whl` | Python wheel file | +| `xpi` | Mozilla XPI module file | +| `xz` | LZMA2 archive | +| `zip` | Zip archive | +| `zlib` | zlib archive | +| `zst` | Zstandard file (zstd) | +| `zpaq` | Zpaq file | + +See [list of archive formats](https://en.wikipedia.org/wiki/List_of_archive_formats) for more information +regarding archive formats. + diff --git a/plugins/extract/extract.plugin.sh b/plugins/extract/extract.plugin.sh new file mode 100644 index 000000000..2e85ba96f --- /dev/null +++ b/plugins/extract/extract.plugin.sh @@ -0,0 +1,89 @@ +alias x=extract + +extract() { + if [[ $# -eq 0 ]]; then + cat >&2 <<'EOF' +Usage: extract [-option] [file ...] + +Options: + -r, --remove Remove archive after unpacking. +EOF + return 1 + fi + + local remove_archive=1 + if [[ "$1" == "-r" || "$1" == "--remove" ]]; then + remove_archive=0 + shift + fi + + local pwd="$PWD" + while [[ $# -gt 0 ]]; do + if [[ ! -f "$1" ]]; then + echo "extract: '$1' is not a valid file" >&2 + shift + continue + fi + + local success=0 + local file="$1" full_path="$(realpath "$1")" + local extract_dir="${file%.*}" + + if [[ "${extract_dir}" =~ ".tar$" ]]; then + extract_dir="${extract_dir%.*}" + fi + + if [[ -e "$extract_dir" ]]; then + local rnd="$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 5)" + extract_dir="${extract_dir}-${rnd}" + fi + + mkdir -p "$extract_dir" + cd "$extract_dir" || return + echo "extract: extracting to $extract_dir" >&2 + + case "${file,,}" in + *.tar.gz|*.tgz) [[ $(command -v pigz) ]] && tar -I pigz -xvf "$full_path" || tar zxvf "$full_path" ;; + *.tar.bz2|*.tbz|*.tbz2) [[ $(command -v pbzip2) ]] && tar -I pbzip2 -xvf "$full_path" || tar xvjf "$full_path" ;; + *.tar.xz|*.txz) [[ $(command -v pixz) ]] && tar -I pixz -xvf "$full_path" || tar --xz -xvf "$full_path" || xzcat "$full_path" | tar xvf - ;; + *.tar.lzma|*.tlz) tar --lzma -xvf "$full_path" || lzcat "$full_path" | tar xvf - ;; + *.tar.zst|*.tzst) tar --zstd -xvf "$full_path" || zstdcat "$full_path" | tar xvf - ;; + *.tar) tar xvf "$full_path" ;; + *.tar.lz) [[ $(command -v lzip) ]] && tar xvf "$full_path" ;; + *.tar.lz4) lz4 -c -d "$full_path" | tar xvf - ;; + *.tar.lrz) [[ $(command -v lrzuntar) ]] && lrzuntar "$full_path" ;; + *.gz) [[ $(command -v pigz) ]] && pigz -cdk "$full_path" > "${file%.*}" || gunzip -ck "$full_path" > "${file%.*}" ;; + *.bz2) [[ $(command -v pbzip2) ]] && pbzip2 -d "$full_path" || bunzip2 "$full_path" ;; + *.xz) unxz "$full_path" ;; + *.lrz) [[ $(command -v lrunzip) ]] && lrunzip "$full_path" ;; + *.lz4) lz4 -d "$full_path" ;; + *.lzma) unlzma "$full_path" ;; + *.z) uncompress "$full_path" ;; + *.zip) unzip "$full_path" ;; + *.rar) unrar x -ad "$full_path" ;; + *.rpm) rpm2cpio "$full_path" | cpio --quiet -id ;; + *.7z) 7z x "$full_path" ;; + *.deb) + mkdir -p "control" "data" + ar vx "$full_path" > /dev/null + (cd control && extract ../control.tar.*) + (cd data && extract ../data.tar.*) + rm -f *.tar.* debian-binary + ;; + *.zst) unzstd --stdout "$full_path" > "${file%.*}" ;; + *.cab|*.exe) cabextract "$full_path" ;; + *.cpio|*.obscpio) cpio -idmvF "$full_path" ;; + *.zpaq) zpaq x "$full_path" ;; + *.zlib) zlib-flate -uncompress < "$full_path" > "${file%.*}" ;; + *) + echo "extract: '$file' cannot be extracted" >&2 + success=1 ;; + esac + + if [[ $success -eq 0 && $remove_archive -eq 0 ]]; then + rm "$full_path" + fi + shift + cd "$pwd" || return + done +}