通常,我会取消存档,$ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zip
但有时我会变得懒惰,只是在任意文件夹中进行操作,$ unzip *.zip
因此有时会弄乱其他内容。我将在这里列出一些方法——一些存档版本肯定有蹩脚的标志,而其他版本则更斯巴达,我对后者更感兴趣。
有一些取消存档的方法,还有其他方法吗?
$ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;
缺点是它列出了*.zip
目录,因此您需要-ok
在许多*.zip
匹配项中使用 Slow , Slow ,并且由于某种原因,它似乎并不匹配提取的所有内容。如果提取的文件量较少,逐一提取,速度慢、繁琐且容易出错。
当我想确定存档的内容是否实际上是一个文件夹时,我有时会使用 , 进行检查
$ unzip -l *.bsd
,至少在 obsd 的解压缩版本中有效。
如果您指的是某些归档工具,请在适当的时候说明它们。但要保持简单——我更感兴趣的是你如何做到这一点,而不是单个工具。
答案1
按名字
您可以生成存档中的文件列表并删除它们,尽管这对于 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
使用保险丝
您可以(在大多数 unice 上)使用,而不是依赖外部工具保险丝使用普通文件系统命令操作档案。
您可以使用保险丝拉链查看 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
按日期
假设除了您的提取之外,同一层次结构中没有其他任何活动,您可以通过最近的文件来判断提取的文件时间。如果您刚刚创建或移动了 zip 文件,则可以将其用作截止;否则用于ls -lctr
确定合适的截止时间。如果您想确保不删除拉链,则没有理由进行任何手动批准: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
再运行)。
答案2
我感觉很愚蠢,无论如何,当我遇到类似的问题时,我挠头写了这个脚本。我使用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
答案3
将存档中的文件列表提供给 怎么样xargs rm
?
那将是tar -tf tarbomb.tar | xargs rm
或unzip --list zipbomb.zip | xargs rm
。
答案4
我在 zsh 中使用以下函数:
ununzip () {
rm -r $(unzip -l $1 | grep -v 'Archive:' | \
grep '[/.]' | sed 's![^a-zA-Z]([a-zA-Z./])!\1!')
}
即命令替换以删除已清理的输出中的所有文件unzip -l
。
tar tvf
可以以类似的方式使用。