stderr과 stdout이 혼합된 tar 파일을 수정하는 방법은 무엇입니까?

stderr과 stdout이 혼합된 tar 파일을 수정하는 방법은 무엇입니까?

복구하려는 tar 파일이 있습니다. 문제는 tar의 stderr이 그것과 혼합되어 있어서 stdout파일이 다음과 같다는 것입니다:

% head android-1435613730.tar
tar: removing leading '/' from member names
factory/0000775000175100017510000000000007033241671011512 5ustar  radioradiofactory/
factory/lost+found/0000700000000000000000000000000000000000000013242 5ustar  rootrootfactory/lost+found/
tar: /factory/lost+found: Permission denied
factory/wifi/0000770000175000017510000000000007033241625012667 5ustar  systemradiofactory/wifi/
tar: /factory/wifi: Permission denied
factory/imei/0000775000175100017510000000000007033241600012425 5ustar  radioradiofactory/imei/
tar: can't open '/factory/nv_data.bin': Permission denied
tar: can't open '/factory/nv_data.bin.md5': Permission denied
factory/bluetooth/0000755000175100017510000000000007033241674013520 5ustar  radioradiofactory/bluetooth/

다음과 같은 오류 메시지를 제거해 보았습니다.

% grep --color=never -v --binary-file=text '^tar:.*$' android-1435613730.tar | tar -tv
drwxrwxr-x radio/radio       0 1999-12-31 16:00 factory/
tar: Skipping to next header
drwx------ install/all_a124  0 2015-06-29 13:51 acct/uid/50124/
tar: Skipping to next header
tar: Exiting with failure status due to previous errors

그러나 보시다시피 이로 인해 오류가 발생합니다. (저는 끔찍한 바이너리 데이터 파일 덤프를 제공하지 않을 것입니다.진짜필요. )

또한 이 파일은 상당히 크고(6.7GB) 사용 가능한 코어나 스왑이 그렇게 많지 않다는 점을 지적해야 합니다.

tar이 타르볼은 이를 생성하는 데 사용된 GNU Tar 1.27.1을 사용하여 압축을 풀고 있습니다.

@kos의 제안에 따라 Perl을 사용해 보았습니다.

% <android-1435613730.tar perl -pe 's/\n?tar: [^\n]*\n//sg' | tar -tv
drwxrwxr-x radio/radio       0 1999-12-31 16:00 factory/
tar: Skipping to next header
drwx------ install/all_a83   0 2015-06-29 13:55 acct/uid/50083/
tar: Skipping to next header
tar: Exiting with failure status due to previous errors

귀하의 편의를 위해 문제를 재현하는 스크립트는 다음과 같습니다.

#!/bin/sh
TMPDIR=$(mktemp -d)
cd $TMPDIR
for i in test test2 test3; do
    mkdir $i
    echo $i > $i/$i
done
chmod 000 test2/test2
chmod 000 test3
tar -c test* > broken.tar 2>&1

echo "Created corrupt tarball in $TMPDIR"

내 타르볼에는 중간에 오류가 섞여 있지만 여기서는 재현할 수 없는 것 같습니다.

답변1

stdout합계 가 라인 버퍼링되고 둘 중 하나의 행이 항상 검색 가능 하다면 혼합하는 것은 문제가 되지 않습니다. 합계가 라인 버퍼링되고 행을 쉽게 검색할 수 있는 stderr프로그램의 출력을 생각해 보세요 .stdoutstderrstderr

$ cat file
xxxxxxxxxx
tar: ----------
yyyyyyyyyy
tar: ----------
zzzzzzzzzz
tar: ----------

다음을 사용하여 둘 중 하나를 추출하는 것은 grep문제가 되지 않습니다 .

$ < file grep -v ^tar
xxxxxxxxxx # stdout line 1
yyyyyyyyyy # stdout line 2
zzzzzzzzzz # stdout line 3
$ < file grep ^tar
tar: ---------- # stderr line 1
tar: ---------- # stderr line 2
tar: ---------- # stderr line 3

stdout그러나 어느 시점에서 버퍼링 동작이 버퍼링 없음으로 변경되는 경우를 고려하십시오.

x
tar: ----------
xxxxxxxxxyyy
tar: ----------
yyyyyyyzzzzz
tar: ----------
zzzzz

추출 stdout및 사용grep 하나의 질문:

$ < file grep -v ^tar
x # wrong stdout line 1
xxxxxxxxxyyy # wrong stdout line 2
yyyyyyyzzzzz # wrong stdout line 3
zzzzz # wrong stdout line 4

이 시도:

< file perl -0777pe 's/\n?tar: [^\n]*\n//g' > newfile

[가장자리] 경우를 제외하고 stdout원본 콘텐츠는 파일에서 추출되어야 합니다.

$ < file perl -0777pe 's/\n?tar: [^\n]*\n//g'
xxxxxxxxxxyyyyyyyyyyzzzzzzzzzz

관련 정보