相当于解压缩中的tar的“ --strip-components = 1”?


48

我有一个脚本,可将tar.gz文件提取到指定的子目录mysubfolder中

mkdir mysubfolder; tar --extract --file=sourcefile.tar.gz --strip-components=1 --directory=mysubfolder;

有什么等效的方法可以执行zip文件吗?


2
只需使用bsdtar
下雨了

Answers:


26

正如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如果它不存在,它将自动为您创建)


这不会像我希望的那样解压缩到现有的目录结构中(我尝试使用。代替mysubfolder)。我最终只是解压缩(解压缩zip-with-top-dir.zip),然后复制(cp -rv提取顶部-zip-dir / *)。
catgofire '16

4

我在的手册页中unzip找不到这样的选项,因此恐怕这是不可能的。:(

但是,(取决于具体情况)您可以解决它。例如,如果您确定在zip文件中唯一的顶级目录的名称foo-后面是版本号,则可以执行以下操作:

cd /tmp
unzip /path/to/file.zip
cd foo-*
cp -r . /path/to/destination/folder

好的方法,但是有点不完整:您仍然会拥有foo * dir及其完整的提取内容。
MestreLion

是的,我没有rm -rf foo-*故意添加,因为这可能很危险。如果已经有一个名为的文件夹foo-bar怎么办?请注意,提取是在/tmp文件夹中完成的,该文件夹会不时自动清空。
Mathias Bynens

这就是为什么我使用&&以下方法将操作链接起来:给定步骤仅在上一步成功的情况下发生,因此最后一个(the rm)仅在所有步骤均无错误完成的情况下运行。
MestreLion

2
这就是为什么永远不要将用户/tmp/some-hardcoded-folder-name用作临时文件夹,而应该使用mktemp它的原因:它保证不会有这样的现有文件夹。在下面检查我的答案。
MestreLion

1

您可以使用-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).
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.