tar 파일 추출 엉망 실행 취소


34

방금 깔끔한 디렉토리에 파일을 엉망으로 만드는 아카이브를 압축 해제했습니다. 예를 들면 다음과 같습니다.

user@comp:~/tidy$ tar xvf myarchive.tar
file1
file2
dir1/
dir1/file1
dir1/subdir1/
dir1/subdir1/file1
dir2/
dir2/file1
...

tar 파일이 단일 폴더 (예 :)로 구성 될 것으로 예상 myarchive/했지만 그렇지 않았습니다! 이제 약 190 개의 파일과 디렉토리가 구성되어있는 디렉토리에 디지털로 바프되었습니다. 이 untar 파일은 정리해야합니다.

이것을 "취소"하고이 아카이브에서 추출한 파일과 디렉토리를 삭제하는 방법이 있습니까?


아래의 훌륭한 답변에 감사드립니다. 요약 하면 다음은 두 단계 (1) 파일 삭제 및 (2) 빈 디렉토리 구조를 역 패킹 순서로 삭제하는 것입니다 (외부 디렉토리를 먼저 삭제).

tar tf myarchive.tar | xargs -d'\n' rm
tar tf myarchive.tar | tac | xargs -d'\n' rmdir

그리고 echo이후 에 추가하여 명령의 드라 이런을 미리 보는 것이 더 안전합니다 xargs.


아카이브에 파일을 나열하고 현재 디렉토리에서 파일을 삭제할 수는 있지만 잠재적으로 데이터를 손상시킬 수 있습니다 (보관하려는 데이터). 나는 또한 bash 스크립트를 작성하는 방법을 모른다. 그래서 거기에서 도울 수 없다.
Bob

다행히도 아무 것도 덮어 쓰지 않았습니다!
Mike T

나는 담당자를 따르지 않고 나는 이것을 어떻게 넣었 든 까다로운 소리를 낼 것이 두렵다. (나는 slhck의 대답을 좋아했고 +1 : 그것을했다. 하지 내 세계),하지만 당신은 파이프 내 제안 대답을 사용하여 종료하고 xargs( tac대신은 sort -r) 단지 화장품,하지만 당신은 당신이 코멘트에 설명 된대로, 당신을 맞지 않았던, 그 과정 치환과 대답을 받아? 또한 xargs -d'\n'향후 사용자를 위해 요약하려는 경우 게시물에 스위치를 지정하여 파일 이름의 공백으로 물리지 않도록하십시오.
Daniel Andersson

@DanielAndersson, 나는 -d'\n'지금까지 의 필요성을 결코 이해하지 못했으며, 추가 분석을 통해 당신의 대답은 실제로 내가 사용한 것에 더 가깝습니다.
Mike T

@Daniel의 솔루션이 마음에 들었습니다. :) -d'\n'당신이 줄 xargs을 바꾸지 말고 줄 을 바꾸지 않으면 스페이스에 파일을 넣을 수 있다는 사실 이 필요 합니다. 이름 folder1/some filefolder1/some및 로 읽습니다 name.
slhck

답변:


36
tar tf archive.tar

내용을 한 줄씩 나열합니다.

이것은 xargs직접 파이프 될 수 있지만 주의하십시오 : 삭제를 매우 신중하게 수행하십시오. 당신은 하지 않습니다 단지 원하는 rm -r모든 tar tf것이 풀기 전에 비우되지 않은 디렉토리를 포함 할 수 있기 때문에, 당신을 알려줍니다!

넌 할 수있어

tar tf archive.tar | xargs -d'\n' rm -v
tar tf archive.tar | sort -r | xargs -d'\n' rmdir -v

먼저 아카이브에 있던 모든 파일을 제거한 다음 비어있는 디렉토리를 제거하십시오.

sort -r가장 깊은 디렉토리를 먼저 삭제하려면 glennjackman 이 수락 된 답변에 대한 의견 tac대신 제안 되었습니다 sort -r. 이는 tar출력이 충분하기 때문에 작동합니다 . 그렇지 않으면 dir1빈 디렉토리 dir2가 하나 포함 된 케이스 는 제거 되기 전에 비어 있지 않기 때문에 통과 dir1후에 남겨 집니다.rmdirdir2

이것은 많은 것을 생성합니다

rm: cannot remove `dir/': Is a directory

rmdir: failed to remove `dir/': Directory not empty
rmdir: failed to remove `file': Not a directory

성가신 경우이 기능을 종료하십시오 2>/dev/null. 그러나 프로세스에 대한 정보를 최대한 많이 유지하고 싶습니다.

올바른 파일과 일치 할 때까지 수행하지 마십시오. 그리고 아마도 rm -i모든 것을 확인 하려고 노력하십시오 . 백업을하고 아침 식사를하고 양치질을하십시오.


예, -d'\n'옵션을 에 전달하는 것이 좋습니다 xargs.
Stéphane Gimenez

@slhck와 Stéphane : 아, 그래요. 업데이트하겠습니다. 방금 작은 테스트 사례를 수행했지만 파일에 공백이 없었습니다.
Daniel Andersson

1
BSD xargs는을 가지고 있지 -d않으므로 나처럼 가난한 영혼이라면 GNU 변형이 필요합니다.
slhck

10

tar 파일의 내용을 다음과 같이 나열하십시오.

tar tzf myarchive.tar

그런 다음 해당 목록을 반복하여 해당 파일 이름을 삭제하십시오.

while IFS= read -r file; do echo "$file"; done < <(tar tzf myarchive.tar.gz)

이것은 여전히 삭제 될 파일을 나열 합니다. 교체 echorm당신이 정말로 확실이 제거하려는 사람들이다 있다면. 그리고 확실하게 백업을 만들 수도 있습니다.

두 번째 단계에서 남아있는 디렉토리를 제거하십시오.

while IFS= read -r file; do rmdir "$file"; done < <(tar tzf myarchive.tar.gz)

이렇게하면 디렉토리가 이미 존재하는 경우 디렉토리가 삭제되지 않습니다.


@glennjackman의 또 다른 멋진 트릭은 가장 깊은 파일부터 시작하여 파일 순서를 유지합니다. echo완료되면 다시 제거하십시오 .

tar tvf myarchive.tar | tac | xargs -d'\n' echo rm

그런 다음 정상적인 rmdir정리 가 이어질 수 있습니다 .


파이프를 쓰는 이상한 방법.
Stéphane Gimenez

파이프 가 아닙니다 . 그것은의 프로세스 대체 와 함께 사용할 때 나는이 이상 간단한 배관을 선호 while레코드 집합을 통해 루프. 익숙해 졌어 @ sté
slhck

1
약간의 지연으로 인해 죄송합니다.를 사용 rm -rf하면 아카이브가 아닌 아카이브와 이름이 같은 디렉토리에있는 파일을 삭제할 수 있습니다. 여기서 더주의 rmdir해서 두 번째 패스에 사용하십시오 .
Stéphane Gimenez

1
실제로 두 번째 단계의 패스 rmdir는 디렉토리의 각 레벨 중첩에 대해 실행해야합니다. 따라서 subdir1첫 번째 패스에서 정리 되지만 dir1당시 비어 있지 않은 경우 처음 삭제하려고 시도했기 때문에 그대로 둡니다 . 파일 목록을 역순으로 정렬 할 수 있으면이 명령을 한 번 수행 할 수 있습니다.
Mike T

3
역순으로 삭제하려면 : tar tvf arch.tar | tac | xargs echo rm(자신감이있을 때 에코 제거)
glenn jackman

2

추출 된 파일을 가져 와서 서브 디렉토리로 이동하여 기본 폴더를 정리할 가능성이 있습니다.

    #!/usr/bin/perl -w

    use strict;
    use Getopt::Long;

    my $clean_folder = "clean";
    my $DRY_RUN;
    die "Usage: $0 [--dry] [--clean=dir-name]\n"
        if ( !GetOptions("dry!" => \$DRY_RUN,
                         "clean=s" => \$clean_folder));

    # Protect the 'clean_folder' string from shell substitution
    $clean_folder =~ s/'/'\\''/g;

    # Process the "tar tv" listing and output a shell script.
    print "#!/bin/sh\n" if ( !$DRY_RUN );
    while (<>)
    {
        chomp;

        # Strip out permissions string and the directory entry from the 'tar' list
        my $perms = substr($_, 0, 10);
        my $dirent = substr($_, 48);

        # Drop entries that are in subdirectories
        next if ( $dirent =~ m:/.: );

        # If we're in "dry run" mode, just list the permissions and the directory
        # entries.
        #
        if ( $DRY_RUN )
        {
            print "$perms|$dirent\n";
            next;
        }

        # Emit the shell code to clean up the folder
        $dirent =~ s/'/'\\''/g;
        print "mv -i '$dirent' '$clean_folder'/.\n";
    }

이것을 파일에 저장하십시오 fix-tar.pl 하고 다음과 같이 실행하십시오.

$ tar tvf myarchive.tar | perl fix-tar.pl --dry

tar목록이 내 것과 같다는 것을 확인합니다 . 다음과 같은 출력이 표시되어야합니다.

-rw-rw-r--|batch
-rw-rw-r--|book-report.png
-rwx------|CaseReports.png
-rw-rw-r--|caseTree.png
-rw-rw-r--|tree.png
drwxrwxr-x|sample/

그것이 좋아 보인다면 다음과 같이 다시 실행하십시오.

$ mkdir cleanup
$ tar tvf myarchive.tar | perl fix-tar.pl --clean=cleanup > fixup.sh

fixup.sh스크립트는 최상위 파일과 디렉토리를 "깨끗한"폴더 (이 경우 폴더)로 이동시키는 쉘 명령입니다 cleanup. 이 스크립트를 들여다보고 모든 것이 정결하다는 것을 확인하십시오. 그렇다면 다음과 같이 엉망을 정리할 수 있습니다.

$ sh fixup.sh

나는 이런 종류의 정리를 선호한다 tar xv.

참고 : 초기 드라이 런 출력이 올바르게 보이지 않으면 두 숫자를 사용하여 바이올린을 칠 수 있습니다. substr 함수 호출 적절 해 보일 때까지 . $perms변수는 그래서 정말에만 실행 건조에 사용되는 $dirent하위 문자열 요구에 적절한 될 수 있습니다.

또 다른 사항 : 목록 의 사용자 이름 및 / 또는 그룹 이름으로 인해 이름이 예측할 수없는 열로 시작하는 경우이 tar옵션 을 사용해야 할 수도 있습니다 .--numeric-ownertar


1

이런 종류의 (반사회적) 아카이브는 그것이하는 일 때문에 타르 폭탄이라고합니다. 이 중 하나가 "폭발"되면 다른 답변의 솔루션이 내가 제안한 것보다 훨씬 낫습니다.

그러나 가장 좋은 "해결책"은 처음에 문제를 방지하는 것입니다.

가장 쉬운 방법은 항상 tar 아카이브를 빈 디렉토리에 압축 해제하는 것입니다. 최상위 디렉터리가 포함되어 있으면 원하는 대상으로 이동하면됩니다. 그렇지 않은 경우 작업 디렉토리 (비어 있던 디렉토리)의 이름을 바꾸고 원하는 위치로 옮기십시오.

처음으로 올바르게 가져 오려면 tar -tvf archive-file.tar | less는 아카이브의 내용을 나열하므로 아카이브 구조를 확인한 다음 원하는 위치로 추출하는 데 필요한 작업을 수행 할 수 있습니다.

t 옵션은 아카이브의 내용을 검사하여 원하는 내용이 있는지 확인하려는 경우에도 유용합니다. 그렇다면 선택적으로 원하는 파일을 추출 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.