如果存档在根目录中包含多个文件,我想创建一个以文件名命名的目录(不带扩展名)。如果存档仅包含一个目录,那么我想简单地提取它。假设我有以下存档:
# file: withdir.zip
somedir/alpha
somedir/beta
somedir/gamma
如果我将其提取到当前目录中,我希望将其简单地提取(unzip withdir.zip
):
somedir/alpha
somedir/beta
somedir/gamma
现在假设有以下存档:
# file: nodir.zip
alpha
beta
gamma
当我运行时,unzip nodir.zip
我最终会用三个文件弄乱当前目录:
alpha
beta
gamma
我宁愿跑unzip -d nodir nodir.zip
:
nodir/alpha
nodir/beta
nodir/gamma
如果我使用 nautilus 并右键单击“Extract Here”。它的行为完全符合预期。但不幸的是,我还没有找到unzip
或
7z
产生相同行为的命令行开关。如何实现这一目标?我可以使用其他工具(无 GUI)吗?
答案1
我会做这样的事情(zsh 语法):
unz() (
tmp=$(TMPDIR=. mktemp -d -- ${${argv[-1]:t:r}%.tar}.XXXXXX) || exit
print -r >&2 "Extracting in $tmp"
cd -- $tmp || exit
[[ $argv[-1] = /* ]] || argv[-1]=../$argv[-1]
(set -x; "$@"); ret=$?
files=(*(ND[1,2]))
case $#files in
(0) print -r >&2 "No file created"
rmdir -v "../$tmp";;
(1) mv -v -- $files .. && rmdir -v ../$tmp;;
(*) mv -vT ../$tmp ../$tmp:r;;
esac && exit $ret
)
那是:
- 无论如何创建一个目录
- 运行命令
- 取决于命令生成的文件数量:
- 删除该目录(如果它没有创建任何文件)
- 如果它只创建了一个文件/目录,请将其向上移动一级并丢弃我们的目录
- 否则,尝试从临时目录末尾删除随机字符串。
这样,您可以执行以下操作:
unz unzip foo.zip
unz tar xf foo.tar.gz
它假定提取命令的最后一个参数是要提取的文件。它还假定-v
选项使用 GNU 工具。在非 GNU 系统上,您可以删除它们并可能手动进行日志记录。mv -T
也是 GNU 特定的,并且mv
仅强制尝试进行重命名。
答案2
由于unzip
两者7z
都有一个输出到给定目录的开关,您可以创建一个简单的脚本,检查存档根目录中有多少个文件,然后根据需要添加开关。
对于 7z,这更容易,因为它有开关-slt
,这使得输出更易于机器读取。对于 zip 中的每个文件,输出都将包含一行Path = ...
。根目录中的文件不应包含任何/
值。
我编写了一个通过这种方式解压文件的简单脚本:
#!/bin/sh
for archive in "$@"; do
# count files in root dir
rootfiles=$(7z l -slt "${archive}" | grep -c 'Path = [^/]*$')
# add -o switch, if more than one file in root
# checks for >2, because path of the zip file itself is listed too
if [ $rootfiles -gt 2 ]; then
filename=${archive##*/}
rootname=${filename%.*}
opt="-o${rootname}"
fi
#unpack
7z x "${opt}" "${archive}"
done
编辑:脚本现在也适用于 zip
答案3
巡警处理不同类型的存档并在存档包含多个文件的情况下创建子目录,以防止提取的文件使工作目录混乱。
创建档案
patool create archive.zip somedirectory
提取存档
patool extract archive.zip
要获取支持的格式列表,请使用patool formats
。
答案4
你也可以使用乌纳尔,当有两个或多个顶级文件时,它默认创建一个包含目录:
$ touch 1 2
$ zip a.zip 1 2
adding: 1 (stored 0%)
adding: 2 (stored 0%)
$ unzip -l a.zip
Archive: a.zip
Length Date Time Name
-------- ---- ---- ----
0 04-29-14 10:56 1
0 04-29-14 10:56 2
-------- -------
0 2 files
$ unar a.zip
a.zip: Zip
1 (0 B)... OK.
2 (0 B)... OK.
Successfully extracted to "a".
$ ls a
1 2
添加-d
以始终创建包含目录。