c86ba78e2ff5c5a3e9282a84c0cc220dd3d5f253

Author
Dylan Roman <romand.buitrago@gmail.com>
Committer
GitHub <noreply@github.com>
Date

Message

feat(extract): add support for extracting to a specified directory (#13734)

Diff

 1diff --git a/plugins/extract/_extract b/plugins/extract/_extract
 2index 6641443d3281ef8f13339fd028218a9b6426b607..7d71aeb1b80170c9caee5b0300e7c7397f5fcab2 100644
 3--- a/plugins/extract/_extract
 4+++ b/plugins/extract/_extract
 5@@ -53,5 +53,6 @@ local -a exts=(
 6 
 7 _arguments \
 8   '(-r --remove)'{-r,--remove}'[Remove archive.]' \
 9+  '(-t --to-directory)'{-t,--to-directory}'[Extract to a specific directory.]' \
10   "*::archive file:_files -g '(#i)*.(${(j:|:)exts})(-.)'" \
11     && return 0
12diff --git a/plugins/extract/extract.plugin.zsh b/plugins/extract/extract.plugin.zsh
13old mode 100644
14new mode 100755
15index aed77e7d7ffb57e51285f94f45d3035ca7b474bb..8219f974e3027c12e845b6638200fe4e2dffa2bb
16--- a/plugins/extract/extract.plugin.zsh
17+++ b/plugins/extract/extract.plugin.zsh
18@@ -9,14 +9,41 @@ Usage: extract [-option] [file ...]
19 
20 Options:
21     -r, --remove    Remove archive after unpacking.
22+    -t, --to-directory <dir>  Extract to a specific directory instead of the current one.
23 EOF
24   fi
25 
26   local remove_archive=1
27-  if [[ "$1" == "-r" ]] || [[ "$1" == "--remove" ]]; then
28-    remove_archive=0
29-    shift
30-  fi
31+  local target_directory=""
32+
33+  while (( $# > 0 )); do
34+    case "$1" in
35+      -r|--remove)
36+        remove_archive=0
37+        shift
38+        ;;
39+      -t|--to-directory)
40+        shift
41+        if (( $# == 0 )); then
42+          echo "extract: -t/--to-directory requires a directory argument" >&2
43+          return 1
44+        fi
45+
46+        target_directory="$1"
47+        shift
48+
49+        if [[ ! -d "$target_directory" ]]; then
50+          echo "extract: '$target_directory' is not a valid directory" >&2
51+          return 1
52+        fi
53+
54+        target_directory="${target_directory%/}"
55+        ;;
56+      *)
57+        break
58+        ;;
59+    esac
60+  done
61 
62   local pwd="$PWD"
63   while (( $# > 0 )); do
64@@ -35,6 +62,10 @@ EOF
65       extract_dir="${extract_dir:r}"
66     fi
67 
68+    if [[ -n "$target_directory" ]]; then
69+      extract_dir="$target_directory/${extract_dir:t}"
70+    fi
71+
72     # If there's a file or directory with the same name as the archive
73     # add a random string to the end of the extract directory
74     if [[ -e "$extract_dir" ]]; then
75@@ -126,7 +157,7 @@ EOF
76       # 1. Move and rename the extracted file/folder to a temporary random name
77       # 2. Delete the empty folder
78       # 3. Rename the extracted file/folder to the original name
79-      if [[ "${content[1]:t}" == "$extract_dir" ]]; then
80+      if [[ "${content[1]:t}" == "${extract_dir:t}" ]]; then
81         # =(:) gives /tmp/zsh<random>, with :t it gives zsh<random>
82         local tmp_name==(:); tmp_name="${tmp_name:t}"
83         command mv "${content[1]}" "$tmp_name" \
84@@ -134,9 +165,9 @@ EOF
85         && command mv "$tmp_name" "$extract_dir"
86       # Otherwise, if the extracted folder name already exists in the current
87       # directory (because of a previous file / folder), keep the extract_dir
88-      elif [[ ! -e "${content[1]:t}" ]]; then
89-        command mv "${content[1]}" . \
90-        && command rmdir "$extract_dir"
91+      elif [[ ! -e "${target_directory:-.}/${content[1]:t}" ]]; then
92+        command mv -- "${content[1]}" "${target_directory:-.}/" \
93+        && command rmdir -- "$extract_dir"
94       fi
95     elif [[ ${#content} -eq 0 ]]; then
96       command rmdir "$extract_dir"