如何判断“解压缩”是否会提前创建单个文件夹?

如何判断“解压缩”是否会提前创建单个文件夹?

一种常见的情况是在包含其他工作的目录中包含一个 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 文件是否只包含一个文件夹?

答案1

好吧,你可以只需无条件地提取到子目录中,然后如果它最终仅包含单个项目,则将其删除。

但为什么要去理智且简单的解决方案(由伊尔卡丘),什么时候可以使用awk? :)

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 文件。

答案2

您也可以使用以下命令来提取它,而不是在提取之前检查存档内容unar这将提供您所追求的行为:默认情况下,如果存档包含单个顶级目录,unar则按原样提取它,否则它会创建一个以存档命名的目录并将其提取到那里。您可以使用该选项在所有情况下强制创建目录-d

unar它还具有支持多种存档格式的优点。

答案3

从手册...

[-d 目录]

将文件提取到的可选目录。默认情况下,所有文件和子目录都会在当前目录中重新创建; -d 选项允许在任意目录中提取(始终假设有权写入该目录)。该选项不需要出现在命令行的末尾;它也可以在 zipfile 规范之前(使用正常选项)、紧接在 zipfile 规范之后或在文件和 -x 选项之间接受。选项和目录可以连接在一起,之间没有任何空格,但请注意,这可能会导致正常的 shell 行为被抑制。特别是, -d ~(波浪号) 由 Unix C shell 扩展为用户主目录的名称,但-d~被视为~当前目录的字面子目录。

所以...

unzip -d new_dir zipfile.zip

这将创建一个目录 new_dir,并提取其中的存档,这样即使不先查看,也可以避免每次出现潜在的混乱。看看也很有用man unzip有关手册页的更多帮助

答案4

这是一个很好的 bash one liner,使用默认解压缩:

 while read -r line; do (unzip -d "$(basename "$line" .zip)" "$line"); done < <(find . | grep '.zip')

在包含用于解压缩的 zip 文件的目录中运行此命令。

  • < <将 的结果送入find . | grep '.zip'循环while
  • 然后返回的文件名find存储为line
  • while循环迭代 in 中的文件名line并将它们输入到do
  • 这将使用来自的文件名do创建一个目录basename$line
    • 扩展.zip名被指定为要从字符串中剥离的文本
    • 这仅留下不带扩展名的文件名(基本名称!)
  • 参数-d使用 的基本名称.zip来创建新目录
    • /folder/archive.zip然后变成/folder/archive/unzipped_file.txt等。
    • 这很像 Windows / 7zip 的“提取到”选项
  • 然后将该$line变量用作解压缩的目标。

这款衬垫也可以适用于各种物品!移动文件、压缩文件、复制文件...查找是递归的,因此非常方便!

相关内容