Answers:
正如Mathias所说,unzip
没有这种选择,但是单行bash脚本可以完成这项工作。
问题是:最佳方法取决于您的存档布局。如果内容直接位于存档根目录中(请考虑一下剥离和的混乱情况),则假定单个顶级目录的解决方案将惨遭失败。/a/foo
/b/foo
/foo
/a
/b
同样的失败发生在tar --strip-component
。没有一种万能的解决方案。
所以,剥离的根目录,假设有是一个(并且仅一个):
unzip -d "$dest" "$zip" && f=("$dest"/*) && mv "$dest"/*/* "$dest" && rmdir "${f[@]}"
只要确保第二级的文件/显示目录都没有具备顶级父的相同名称(例如,/foo/foo
)。但是/foo/bar/foo
,/foo/bar/bar
还可以。如果这样做,或者您只是想安全起见,则可以使用临时目录进行提取:
temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
mv "$temp"/*/* "$dest" && rmdir "$temp"/* "$temp"
如果您使用的是Bash,则可以测试顶级是单个目录还是不使用:
f=("$temp"/*); (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] && echo "Single dir!"
说到Bash,您应该打开dotglob
以包含隐藏文件,并且可以将所有内容包装在一个便捷的函数中:
unzip-strip() (
local zip=$1
local dest=${2:-.}
local temp=$(mktemp -d) && unzip -d "$temp" "$zip" && mkdir -p "$dest" &&
shopt -s dotglob && local f=("$temp"/*) &&
if (( ${#f[@]} == 1 )) && [[ -d "${f[0]}" ]] ; then
mv "$temp"/*/* "$dest"
else
mv "$temp"/* "$dest"
fi && rmdir "$temp"/* "$temp"
)
现在将其放在您的~/.bashrc
或中~/.profile
,您将不必再担心它。只需用作:
unzip-strip sourcefile.zip mysubfolder
(请注意,mysubfolder
如果它不存在,它将自动为您创建)
我在的手册页中unzip
找不到这样的选项,因此恐怕这是不可能的。:(
但是,(取决于具体情况)您可以解决它。例如,如果您确定在zip文件中唯一的顶级目录的名称foo-
后面是版本号,则可以执行以下操作:
cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder
rm -rf foo-*
故意添加,因为这可能很危险。如果已经有一个名为的文件夹foo-bar
怎么办?请注意,提取是在/tmp
文件夹中完成的,该文件夹会不时自动清空。
&&
以下方法将操作链接起来:给定步骤仅在上一步成功的情况下发生,因此最后一个(the rm
)仅在所有步骤均无错误完成的情况下运行。
/tmp/some-hardcoded-folder-name
用作临时文件夹,而应该使用mktemp
它的原因:它保证不会有这样的现有文件夹。在下面检查我的答案。
您可以使用-j
垃圾路径(不要创建目录)。仅建议将其用于某些常见的单级归档。具有多级目录结构的档案将被展平-这甚至可能导致文件提取的名称冲突。
从解压缩的手册页中:
-j junk paths. The archive's directory structure is not recreated; all files are deposited in the extraction directory (by default, the current one).