압축을 푸는 방법, tar-xvf -- 어수선한 폴더에 압축을 푸나요?

압축을 푸는 방법, tar-xvf -- 어수선한 폴더에 압축을 푸나요?

보통은 $ 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 버전에서는 작동합니다.

특정 보관 도구를 언급하는 경우 적절한 곳에 설명하십시오. 하지만 단순하게 유지하세요. 저는 개별 도구보다는 어떻게 수행하는지에 더 관심이 있습니다.

답변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-cnewerPrimary는 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비슷한 방식으로 사용할 수 있습니다.

관련 정보