Как разархивировать, разархивировать -xvf - разархивировать в грязной папке?

14

Обычно я разархивирую вещи, $ mkdir newFolder; $ mv *.zip newFolder; $ cd newFolder; $unzip *.zipно иногда я ленюсь и просто делаю их в произвольной папке, $ unzip *.zipпоэтому время от времени путаюсь с другим контентом. Я перечислю здесь некоторые методы - некоторые архивные версии, несомненно, имеют флаги-дерьмо, в то время как другие более спартанские, меня больше интересует последнее.

Некоторые способы деархивировать, есть другие?

  1. $ find . -anewer fileThatExistedBeforeUnarchieving -ok rm '{}' \;Недостатки в том, что в нем перечислены *.zipкаталоги, поэтому вам нужно использовать медленный -ok, медленный со многими *.zipсовпадениями и, по какой-то причине, он не соответствует всему извлеченному.

  2. Если небольшое количество извлеченных файлов, один за другим, медленно, громоздко и подвержено ошибкам.

  3. Когда я хочу убедиться, что содержимое архива действительно является папкой, я иногда проверяю его $ unzip -l *.bsd, работает по крайней мере в unzip-версии obsd.

Если вы имеете в виду определенные инструменты архивации, укажите их, когда это необходимо. Проще говоря, меня больше интересует ПУТИ, как вы это делаете, а не один инструмент.

Руи Ф Рибейро
источник
1
См. Также Расположение случайного извлечения - Как очистить?
Жиль "ТАК - перестань быть злым"
Вот скрипт, который я использую для автоматизации mkdir; unzipвещей, поэтому мне никогда не лень это делать! svn.mikelward.com/svn/scripts/untar
Микель
2
Смотрите этот родственный вопрос и ответы: unix.stackexchange.com/questions/5123/...
Алекс

Ответы:

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 для управления архивами с помощью обычных команд файловой системы.

Вы можете использовать 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 создает представление всей вашей иерархии каталогов, в котором все архивы имеют связанный каталог (с тем же именем, в конце которого стоит # tacked ), который, по-видимому, содержит содержимое архива.

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для определения подходящего времени отключения. Если вы хотите убедиться, что молнии не сняты, нет никаких оснований для ручного одобрения: они findвполне могут их исключить. Вот примеры команд, использующих zsh или find; Следует отметить , что -cminи -cnewerпраймериз не в POSIX , но существуют на Linux (и других систем с GNU находке), * 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
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
phunehehe
источник
0

Как насчет подачи списка файлов в архиве в xargs rm?

Это было бы tar -tf tarbomb.tar | xargs rmили unzip --list zipbomb.zip | xargs rm.

Алекс
источник
2
Указанные команды не будут работать в общем случае, и это опасно, так как вы удаляете файлы. xargsожидает, что его вклад процитирован особым образом, findкоторый не производит. Используйте xargs -I rm {}так, чтобы xargs обрабатывал по одному элементу в строке. Для команды unzip какая у вас реализация? У меня (Debian / Ubuntu) нет --list, только -l, и он не просто печатает имена файлов, поэтому необходима дополнительная обработка.
Жиль "ТАК - перестань быть злым"
@ Жиль: 1) да, это опасно, но, поскольку мы предположительно перезаписали исходные файлы - они уже ушли. 2) Я не говорил о find. 3) вы правы unzip, я не проверял, и, кажется, нет возможности для недекорированных списков. Нет и --listна моей Ubuntu - я просто не тестировал.
Алекс
К сожалению о консервированном ответ заменить tar -tна find. Но мои другие пункты стоят. Существует реальный риск того, что ваша команда, как указано, удалит несвязанный файл.
Жиль "ТАК ... перестать быть злым"
tar -tf tarbomb.tarбудет печатать имена файлов по одному в строке, чтобы вы могли сделать tar -tf tarbomb.tar | while IFS=$'\n' read -r filename; do rm "$filename"; doneили подобное.
Микель
0

Не совсем то, что вы просили, но как насчет использования сценария «unzip all» вместо.

unzip *.zip

Таким образом, выходные данные каждого файла попадают в его собственную директорию.

#!/bin/bash
for f in *.zip ; do unzip -n "$f" -d "${f/%zip/out}"; done
Johan
источник
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 может быть использован аналогичным образом.

Эдд Стил
источник