一种常见的情况是在包含其他工作的目录中包含一个 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 unzip
v6.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
变量用作解压缩的目标。
这款衬垫也可以适用于各种物品!移动文件、压缩文件、复制文件...查找是递归的,因此非常方便!