解压缩时,如何强制unzip / zip不创建子目录?


19

根据zip文件的创建方式,有时会直接提取所有文件,有时会将文件提取到子目录中。

如果后者是正确的,我如何强制unzip命令“忽略”该第一级目录?

例:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
mkdir omeka
unzip omeka-1.5.1.zip -d omeka/
cd omeka/
ll

我得到的是/tmp/omeka/omeka-1.5.1/

total 12
drwxr-xr-x 3 root root 4096 2012-05-08 18:44 ./
drwxrwxrwt 6 root root 4096 2012-05-08 18:44 ../
drwxr-xr-x 5 root root 4096 2012-04-20 14:54 omeka-1.5.1/

我想要的是提取到的文件/tmp/omeka/(一级升级,目录结构中没有版本号)

/tmp/omeka/(files)

我知道我可以使用-j“垃圾路径”选项,但是我想保留子目录结构,而不是顶层目录结构。我怎样才能做到这一点?


ps:我知道可以先提取mv文件,然后提取文件,但是我想看看是否有一种方法可以直接通过unzip命令执行此操作
cwd 2012年

我不知道一个。但是,如果文件名始终与目录名匹配(除扩展名外),则编写提取目录的重命名脚本非常简单。
Mat

3
我知道您正在尝试做什么,但我不建议您这样做。从项目源中剥离版本号不是一个好主意。如果您想要一个没有版本信息的简短名称,则应该正常提取并使用ln -s。这样,您将始终知道您正在运行的版本,并且可以通过切换链接轻松地更新到新版本。
Burton Samograd

@BurtonSamograd-这是理想的选择,但是我仍然好奇是否有一种有效的方法来执行此操作,因为某些软件(以Wordpress为例)将每个版本都放在/wordpress/zip文件中的目录中(没有版本号)。确实可以这样做unzipmv但是却无法控制并且必须分两步进行,这总是让我感到不安。幸运的是,WordPress还具有一种.tar.gz风味:)
cwd 2012年

试试看cd /tmp/omeka && ln -s -T . omeka-1.5.1
詹姆斯·扬曼

Answers:


4

使用FUSE文件系统,该文件系统允许您浏览诸如目录之类的档案,例如AVFS。用于cp将文件提取到您选择的目录中。

mountavfs
cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/omeka-1.5.1 omeka

由于我们假设存档中只有一个顶级目录,因此您可以将其缩短为

cp -Rp ~/.avfs/tmp/omeka-1.5.1.zip\#/* omeka

@Giles是您的专家,可以回答其他人无法回答的所有问题,因此我想这确实是唯一的方法。我希望unzip能够做到这一点,例如指定要提取的文件,例如*/*,而无需安装其他实用程序就可以使用,但是我想没有。谢谢。+1
cwd 2012年

6

如果您的zip文件不包含目录结构,或者您不需要保留它,则可以使用以下命令:

cd /tmp
wget http://omeka.org/files/omeka-1.5.1.zip
unzip -j omeka-1.5.1.zip -d omeka
cd omeka
ll

3

该脚本不是很可靠,但是可以在简单的情况下使用:

...
dest=omeka
unzip omeka-1.5.1.zip -d $dest/

if [ `ls $dest | wc -l` == 1 ]; then
  subdir=`ls $dest`
  mv $dest/$subdir/* $dest/
  rmdir $dest/$subdir
fi

它只是检查以查看是否只有一个子目录,如果有,将所有内容移出该子目录然后将其删除。


2

我今天才注册,所以我无法投票@SteveBennet答案,也不能在此处添加评论。

根据他的回答,我创建了一个如下的递归函数:

...

shopt -s dotglob # To include hidden files in the move command

function moveSub {
  local dest=$1
  if [ `ls $dest | wc -l` == 1 ]; then
    local subdir=`ls $dest`
    moveSub "$dest/$subdir"
    mv $dest/$subdir/* $dest/
    rmdir $dest/$subdir
  fi
}

moveSub "$dest"

就像@SteveBennet所说的那样:该脚本并不健壮,但可以在简单的情况下使用。

希望它有用。


1

需要看起来像patch --strip=n选项

希望有一个类似patch --strip=number(或-pnumber)的选项number在开始时就将路径部分砍掉(请参阅比较和合并文件:补丁目录)。

其他解决方案,适用性

失败的话,还有另一种解决方案,有点怪异,但行得通。就我而言,我想用一个zip的内容覆盖一个充满现有文件的目录,而不先提取整个zip。

当此解决方案起作用并且@Gilles的解决方案可用时,后者也将起作用。但是,该解决方案不需要FUSE文件系统。

怎么做

假设您知道额外的目录,在omeka-1.5.1这种情况下,您可以执行以下操作:

mkdir omeka
ln -s . omeka/omeka-1.5.1 # create a symlink that redirects output
unzip omeka-1.5.1.zip -d omeka/
rm omeka/omeka-1.5.1 # remote symlink

unzip将尝试解压缩到omeka-1.5.1实际上是包含目录的符号链接。结果,文件将omeka直接进入。

可能的变体

您可以想像变体来重定向depeer层次结构的一个或多个部分。

ln -s ../myfoo omeka/omeka-1.5.1/foo
ln -s ../../mybarxyzzy omeka/omeka-1.5.1/subdir/bar

结论

该解决方案有些特定,但是有其用例,而我刚好使用过。


如果您知道路径,那是很好的解决方案!
grepsedawk

可以通过首先列出zip内容(例如使用)来探查路径unzip -l。甚至可以使用脚本找出一部分常见路径的脚本来实现自动化。
StéphaneGourichon

哦,总的来说,如果您知道这条路,那就容易了许多。我使用了-zip -l播放了一下,但是grep / sed / awk比我预期的要多,所以我退出了。
grepsedawk

zipinfo -1可能是一个好的开始。您的用例是什么?
斯特凡纳·古里科

github.com/grepsedawk/wow-config/blob/…在这种情况下,我知道目录:)
grepsedawk

1

您最有可能希望unzip使用该-j选项运行,如:

unzip -j files.zip -d ./output/

但是您可能会对它的行为感到惊讶:

-j垃圾路径。不会重新创建档案的目录结构;所有文件都存放在提取目录中(默认情况下是当前目录)。

如果您files.zip在输出目录中解压缩,./output并且得到以下结果:

./output/files/subfolder1/f1
./output/files/subfolder1/f2

然后该-j选项将为您提供(所有路径均条带化):

./output/f1
./output/f2
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.