一个常见的场景是在一个目录中有一个包含其他工作的 zip 文件:
me@work ~/my_working_folder $ ls
downloaded.zip workfile1 workfile2 workfile3
Run Code Online (Sandbox Code Playgroud)
我想解压缩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/
Run Code Online (Sandbox Code Playgroud)
这可以防止my_working_folder填充大量 zip 文件内容。
我的问题是:有没有更好的方法来确定一个 zip 文件在解压前是否只包含一个文件夹?
好吧,您可以无条件地提取到一个子目录中,然后如果它最终只包含一个项目,则将其删除。
但是,当您可以使用时,为什么要寻求一个理智而简单的解决方案(由ilkkachu 提供)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"
}
Run Code Online (Sandbox Code Playgroud)
又快又脏。适用于 InfoZIP 的unzipv6.0。
您可能希望根据您的需要调整它,例如接受或自动使用附加参数unzip,或为提取子目录使用不同的名称(当前由zip文件名确定)。
哦,我刚刚注意到这个解决方法正确地处理了两种最常见的情况(1. ZIP 文件包含一个包含内容的单个目录,2. ZIP 文件包含许多单独的文件和/或目录),但不会创建一个ZIP 文件的根目录包含多个目录但没有文件时的子目录...
编辑:固定。该awk脚本现在存储 ZIP 文件中包含的每个路径的第一个组件(“前缀”),并在检测到与前一个不同的前缀时立即中止。这会捕获多个文件和多个目录(因为两者都必须具有不同的名称),同时忽略所有内容都包含在同一子目录中的 ZIP 文件。
从手册...
[-d 目录]
将文件提取到的可选目录。默认情况下,所有文件和子目录都会在当前目录中重新创建;-d 选项允许在任意目录中提取(始终假设有权写入该目录)。该选项不需要出现在命令行的末尾;它也可以在 zipfile 规范之前(使用正常选项)、紧接在 zipfile 规范之后或在文件和 -x 选项之间接受。选项和目录可以连接在一起,之间没有任何空格,但请注意,这可能会导致正常的 shell 行为被抑制。特别是,
-d ~(波浪号) 由 Unix C shell 扩展为用户主目录的名称,但-d~被视为~当前目录的字面子目录。
所以...
unzip -d new_dir zipfile.zip
Run Code Online (Sandbox Code Playgroud)
这将创建一个目录 new_dir,并提取其中的存档,这样即使不先查看,也可以避免每次潜在的混乱。看看也很有用man unzip。手册页的更多帮助。