Zip

如何判斷“解壓縮”是否會提前創建一個文件夾?

  • October 9, 2020

一個常見的場景是在一個目錄中有一個 zip 文件和其他工作:

me@work ~/my_working_folder $ ls
downloaded.zip  workfile1  workfile2  workfile3

我想解壓縮downloaded.zip,但我不知道它是否會弄得一團糟,或者它是否很好地創建了自己的目錄。我正在進行的解決方法是創建一個臨時文件夾並在那裡解壓縮:

me@work ~/my_working_folder $ mkdir temp && cp downloaded.zip temp && cd temp
me@work ~/my_working_folder/temp $ ls
downloaded.zip
me@work ~/my_working_folder/temp $ unzip downloaded.zip 
Archive:  downloaded.zip
  creating: nice_folder/

這可以防止my_working_folder填充大量 zip 文件內容。

我的問題是:有沒有更好的方法來確定一個 zip 文件在解壓縮之前是否只包含一個文件夾?

從手冊…

$$ -d exdir $$ 提取文件的可選目錄。預設情況下,所有文件和子目錄都在目前目錄中重新創建;-d 選項允許在任意目錄中提取(總是假設一個人有權寫入該目錄)。這個選項不需要出現在命令行的末尾;它也可以在 zipfile 規範之前(使用普通選項)、在 zipfile 規範之後或在文件和 -x 選項之間接受。選項和目錄可以連接在一起,它們之間沒有任何空格,但請注意,這可能會導致正常的 shell 行為被抑制。特別是, -d ~(波浪號)由 Unix C shell 擴展為使用者主目錄的名稱,但-d~被視為文字子目錄~目前目錄的。

所以…

unzip -d new_dir zipfile.zip

這將創建一個目錄 new_dir,並在其中提取檔案,這樣即使不先查看也可以避免每次都可能造成的混亂。看看也很有用man unzip手冊頁的更多幫助

好吧,如果它最終只包含一個項目,你可以無條件地提取到一個子目錄中並在之後刪除它。

但是,當您可以使用時,為什麼要選擇一個理智而簡單的解決方案(由ilkkachuawk提供) ?:)

sunzip ()
{
   if [ $# -ne 1 ] || ! [ -f "$1" ]
   then
       printf '%s\n' "Expected a filename as the first (and only) argument. Aborting."
       return 1
   fi

   extract_dir="."

   # Strip the leading and trailing information about the zip file (leaving
   # only the lines with filenames), then check to make sure *all* filenames
   # contain a /.
   # If any file doesn't contain a / (i.e. is not located in a directory or is
   # a directory itself), exit with a failure code to trigger creating a new
   # directory for the extraction.
   if ! unzip -l "$1" | tail -n +4 | head -n -2 | awk 'BEGIN {lastprefix = ""} {if (match($4, /[^/]+/)) {prefix=substr($4, RSTART, RLENGTH); if (lastprefix != "" && prefix != lastprefix) {exit 1}; lastprefix=prefix}}'
   then
       extract_dir="${1%.zip}"
   fi

   unzip -d "$extract_dir" "$1"
}

快不髒。適用於 InfoZIP 的unzipv6.0。

您可能希望根據您的需要調整它,例如接受或自動使用附加參數unzip,或者為提取子目錄使用不同的名稱(目前由zip文件名確定)。


哦,我剛剛注意到此解決方法正確處理了兩種最常見的情況(1. ZIP 文件包含一個包含內容的目錄,2. ZIP 文件包含許多單獨的文件和/或目錄),但不會創建當 ZIP 文件的根目錄包含多個目錄但沒有文件時的子目錄…

**編輯:**固定。該awk腳本現在儲存 ZIP 文件中包含的每個路徑的第一個組件(“前綴”),並在檢測到與前一個不同的前綴時中止。這會同時擷取多個文件和多個目錄(因為兩者都必須具有不同的名稱),同時忽略所有內容都包含在同一子目錄中的 ZIP 文件。

引用自:https://unix.stackexchange.com/questions/317721