如何解压缩,解压缩-xvf —在一个混乱的文件夹中解压缩?


14

通常,我会取消存档的工作,$ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zip但是有时我会变得懒惰,只是在任意文件夹中进行操作,$ unzip *.zip因此有时会弄乱其他内容。我将在这里列出一些方法-一些存档版本肯定带有糟糕的标志,而另一些则更加斯巴达式,我对后者更感兴趣。

取消存档的某些方法,还有其他方法吗?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;缺点是它列出了*.zip目录,因此您需要对-ok多个*.zip匹配使用slow ,slow,并且由于某种原因,它似乎与提取的所有内容都不匹配。

  2. 如果提取的文件数量很少,则是一对一,缓慢,繁琐且容易出错。

  3. 当我想确定$ unzip -l *.bsd档案的内容是否实际上是一个文件夹时,有时我会用进行检查,至少在obsd的unzip版本中有效。

如果您指的是某些存档工具,请在适当时注明。不过请保持简单-我对方式如何实现更感兴趣,而不是单一的工具。



这是我用来自动化mkdir; unzip内容的脚本,所以我从来都不懒于这样做! svn.mikelward.com/svn/scripts/untar
Mikel,

2
请参阅以下相关问题和解答:unix.stackexchange.com/questions/5123/…–
Alex

Answers:


11

按名字

您可以生成存档中的文件列表并删除它们,尽管对于诸如unzip或7z之类的存档器而言,这很麻烦,因为它们没有生成普通文件名列表的选项。即使使用tar,也假定文件名中没有换行符。

tar tf foo.tar | while read -r file; do rm -- "$file" done
unzip -l foo.zip | awk '
    p && /^ --/ {p=2}
    p==1 {print substr($0, 29)}
    /^ --/ {++p}
' | while …
unzip -l foo.zip | tail -n +4 | head -n -2 | while …  # GNU coreutils only
7z l -slt foo.zip | sed -n 's/^Path = //p' | while …  # works on tar.*, zip, 7z and more

可以删除文件而不是删除文件,而将它们移动到预期的目标位置。

tar tf foo.tar | while read -r file; do
  if [ -d "$file" ]; then continue; fi
  mkdir -p "/intended/destination/${file%/*}"
  mv -- "$file" "/intended/destination/$file"
done

使用保险丝

不必依赖外部工具,而可以(在大多数情况下)使用FUSE通过普通文件系统命令来操作归档。

您可以使用Fuse-zip窥视一个zip,使用提取,使用cp等列出其内容find

mkdir /tmp/foo.d
fuse-zip foo.zip /tmp/foo.d
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd /tmp/foo.d && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm /tmp/foo.d/**(:"s~/tmp/foo.d/~~"^/)
## Extract the contents where you really want them
cp -Rp /tmp/foo.d /intended/destination
fusermount -u foo.d
rmdir foo.d

AVFS会创建整个目录层次结构的视图,其中所有档案都具有一个关联的目录(名称末尾带有#的相同名称),该目录似乎包含档案内容。

mountavfs
## Remove the files that were extracted mistakenly (GNU/BSD find)
(cd ~/.avfs/"$PWD/foo.zip#" && find . \! -type d -print0) | xargs -0 rm
## Remove the files that were extracted mistakenly (zsh)
rm ~/.avfs/$PWD/foo.zip\#/**/*(:"s~$HOME/.avfs/$PWD/foo.zip#~~"^/)
## Extract the contents where you really want them
cp -Rp ~/.avfs/"$PWD/foo.zip#" /intended/destination
umountavfs

按日期

假设除了提取之外,没有其他活动在同一层次结构中,您可以通过提取的文件最近的ctime告诉它们。如果您刚刚创建或移动了zip文件,则可以将其用作截止文件;否则用于ls -lctr确定合适的截止时间。如果要确保不删除这些zip,则无需进行任何手动批准:find完全可以排除它们。这是使用zsh或find;的示例命令。请注意,-cmin和主目录-cnewer不在POSIX中,而是存在于Linux(和其他具有GNU find的系统),* BSD和OSX上。

find . \! -name '*.zip' -type f -cmin -5 -exec rm {} +  # extracted <5 min ago
rm **/*~*.zip(.cm-6)  # zsh, extracted ≤5 min ago
find . -type f -cnewer foo.zip -exec rm {} +  # created or moved after foo.zip

使用GNU find,FreeBSD和OSX,另一种指定截止时间的方法是创建一个文件并将touch其mtime设置为截止时间。

touch -d … cutoff
find . -type f -newercm cutoff -delete

可以删除文件而不是删除文件,而将它们移动到预期的目标位置。这是使用GNU / * BSD / OSX查找的一种方法,可根据需要在目标位置创建目录。

find . \! -name . -cmin -5 -type f -exec sh -c '
    for x; do
      mkdir -p "$0/${x%/*}"
      mv "$x" "$0/$x"
    done
  ' /intended/destination {} +

等效于Zsh(几乎:这是一个完整的目录层次结构,而不仅仅是将包含文件的目录):

autoload zmv
mkdir -p ./**/*(/cm-3:s"|.|/intended/destination|")
zmv -Q '(**/)(*)(.cm-3)' /intended/destination/'$1$2'

警告,我尚未测试此答案中的大多数命令。在删除文件之前,请务必查看文件列表(echo先运行,然后运行rm)。


我今天终于遇到了这个问题。作为根!最后,我使用了“按姓名”和“按日期”的组合
phunehehe 2011年

1

我感到很愚蠢,无论如何,当我遇到类似的问题时,我还是挠头写了这个脚本。我使用cpio-it标志来获取文件列表;您可以将等效命令用于其他存档器。棘手的部分是,cpio归档文件来自initrd,我提取到/,因此许多文件夹和文件的名称与工作系统中的名称相同。幸运的是,cpio不会覆盖任何现有文件。我使用时间检查来确保不删除错误命令之前存在的任何内容。

#! /bin/sh

files=$(cpio -it < /mnt/temp/lglive.cpio)

for i in ${files}
do
    name=$(stat -c "%n" ${i})
    time=$(stat -c "%Y" ${i})
    # Time of the creation of the mess: 1296457595
    if [[ ${time} -gt 1296457590 && ${time} -lt 1296457600 ]]
    then
        if [[ -f ${name} ]]
        # If it is a file, it must have been created as part of the mess.
        then
            echo "rm ${name}"
        elif [[ -d ${name} ]]
        # If it is a directory, it may have been part of the mess
        # or maybe some files underneath it is created as part of the mess.
        then
            if [[ $(ls -A ${name}) ]]
            # If the directory contains something then don't delete it.
            then
                echo "${name} is not empty"
            # If the directory is empty then assume it is rubbish.
            else
                echo "rmdir ${name}"
            fi
        fi
    fi
done

echo "Files and directories still exist after the removal:"
for i in ${files}
do
    if [[ -e ${i} ]]
    then
        echo ${i}
    fi
done

0

如何将存档中的文件列表提供给xargs rm

那将是tar -tf tarbomb.tar | xargs rmunzip --list zipbomb.zip | xargs rm


2
给出的命令在通常情况下不起作用,这很危险,因为您要删除文件。xargs期望它的输入以find不产生异常的方式被引用。使用xargs -I rm {}xargs代替每行处理一项。对于unzip命令,您有什么实现?我的(Debian / Ubuntu)没有--list,只有-l,并且不只是打印文件名,因此需要额外的处理。
吉尔(Gilles)“所以,别再邪恶了”

@吉尔斯:1)是的,这很危险,但是由于我们可能已经覆盖了原始文件,所以它们已经不存在了。2)我不是在谈论find。3)您的unzip判断是正确的,但我没有测试过,而且似乎没有选择进行未修饰清单的选择。没有--list在我的Ubuntu,以及-我只是没有测试。
Alex

很抱歉的罐头回应,替代tar -tfind。但是我的其他观点仍然成立。确实存在这样的风险,即您给出的命令将删除不相关的文件。
吉尔斯(Gilles)“所以,别再邪恶了”,2010年

tar -tf tarbomb.tar将每行打印一个文件名,所以您可以这样做tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; done或类似。
Mikel

0

并不是您真正要求的,而是如何使用“全部解压缩”脚本。

unzip *.zip

这样,每个文件的输出将进入其自己的目录。

#!/bin/bash
for f in *.zip ; do unzip -n "$f" -d "${f/%zip/out}"; done

0

我在zsh中使用以下功能:

ununzip () {
    rm -r $(unzip -l $1 | grep -v 'Archive:' | \
    grep '[/.]' | sed 's![^a-zA-Z]([a-zA-Z./])!\1!')
}

即命令替换以删除清理输出中的所有文件unzip -l

tar tvf 可以类似的方式使用。

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.