이진 파일의 내용을 되 돌리는 방법은 무엇입니까?


11

파일 확장자가없는 데이터 파일 을 찾은 문제를 해결하고있었습니다 . 이 file명령은임을 나타냅니다 data file (application/octet-stream). 이 hd명령은 GNP를 보여줍니다 . 마지막 줄에. 따라서이 파일을 뒤집 으면 .PNG 형식 파일을 얻습니다 . 모든 곳을 검색했지만 바이너리 파일의 내용을 뒤집는 방법을 설명하는 솔루션을 찾지 못했습니다.

답변:


11

xxd(에서 vim) 및 tac(GNU의로 coreutils에서, 또한 tail -r일부 시스템) :

< file.gnp xxd -p -c1 | tac | xxd -p -r > file.png

vi.stackexchange.com/a/2237/10649 와 결합 할 수있는 방법이 있습니까? 나는 운없이 모든 종류의 조합을 시도했다 :(
Iulian Onofrei

모든 파일을 미러링하므로 해결책이 아닙니다.
Philippe Delteil

@PhilippeDelteil, 모든 파일미러링 하면 OP가 요구하는 것이 무엇입니까? 다른 무엇을 하시겠습니까?
Stéphane Chazelas

4

에서 zsh(유일한 고려해야하려는 경우가 아니면 내부적으로 (바이너리 데이터를 처리 할 수있는 쉘 접근 방식을 인코딩하는 경우 ksh93의 64 기수 )) :

zmodload zsh/mapfile
(LC_ALL=C; printf %s ${(s::Oa)mapfile[file.gnp]} > file.png)
  • LC_ALL=C: 문자는 바이트입니다
  • $mapfile[file.gnp]: file.gnp파일 내용
  • s::: 문자열을 바이트 구성 요소로 분할
  • Oa: 해당 배열의 rray 아래 첨자 O에 리버스 rdera

1
zsh이진 데이터를 처리 할 수있는 유일한 쉘은 아닙니다.
fpmurphy

2

다음을 사용하여 이진 파일을 되 돌리는 한 가지 방법이 ksh93있습니다. 이해하기 쉽도록 코드를 "느슨하게"남겨 두었습니다.

#!/bin/ksh93

typeset -b byte

redirect 3< image.gpj || exit 1

eof=$(3<#((EOF)))

read -r -u 3 -N 1 byte
printf "%B" byte > image.jpg
3<#((CUR - 1))

while (( $(3<#) > 0 ))
do
    read -r -u 3 -N 1 byte
    printf "%B" byte >> image.jpg
    3<#((CUR - 2))
done

read -r -u 3 -N 1 byte
printf "%B" byte >> image.jpg

redirect 3<&- || echo 'cannot close FD 3'

exit 0

좋은. 그것은 전체 파일을 메모리에 저장하지 않는 유일한 대답입니다. 그러나 파일의 각 바이트 (및 base64와의 변환)에 대해 여러 시스템 호출을 수행한다는 점에서 매우 비효율적이므로 메모리에 맞지 않는 파일에는 적합하지 않습니다. 내 컴퓨터에서는 약 10KB / s의 파일을 처리합니다.
Stéphane Chazelas

read위 의 첫 번째 파일은 파일 끝에서 수행 된대로 아무것도 읽지 않아야합니다.
Stéphane Chazelas

너무 느린 이유를 이해하려고 노력, 나는 아래를 실행하려 strace하고 ksh93이 파일 내에서 여기 저기를 추구하고, 한 번에 많은 양을 읽어 경우, 매우 이상하게 행동 것으로 보인다. 아마 github.com/att/ast/issues/15
Stéphane Chazelas

@StephaneChazelas. 왜 상대적으로 느린 지에 대한 수수께끼는 없습니다. 루프 내에서는 바이트를 읽을 때마다 뒤로 검색해야합니다. 한 번에 하나 이상의 바이트를 읽고 쓰면 20 배 이상으로 쉽게 줄일 수 있습니다. 사물의 쓰기 측면도 비슷하게 최적화 될 수 있습니다. 작업 속도를 높이기 위해 다른 많은 기술을 사용할 수 있습니다. 그 운동을 당신에게 맡기겠습니다.
fpmurphy

strace내가 의미하는 바를 보려면 스크립트를 사용해보십시오 . ksh93파일을 수천 번 이상 읽습니다. 예를 들어, 첫 번째 바이트를 읽기 전에 파일 끝에서 64KiB를 찾고 64KiB를 읽은 다음 마지막 바이트 전에 찾고 1 바이트를 읽고 모든 바이트에 대해 비슷한 작업을 수행합니다. base64로 인코딩 된 문자열로 수행 할 수있는 작업은 제한되어 있으므로 한 번에 두 바이트 이상을 읽으면 개별 바이트를 추출하기가 더 어려워집니다.
Stéphane Chazelas

2

펄로 :

perl -0777pe '$_=reverse $_'  [input_file]

성능 테스트:

dd if=/dev/urandom of=/tmp/a bs=1M count=1
LC_ALL=C tac -rs $'.\\|\n' /tmp/a > /tmp/r

time perl -0777pe '$_=reverse $_' /tmp/a         | diff -q - /tmp/r
time xxd -p -c1 /tmp/a | tac | xxd -p -r         | diff -q - /tmp/r
time perl -0777 -F -ape '$_=reverse@F' /tmp/a    | diff -q - /tmp/r
time LC_ALL=C tac -rs $'.\\|\n' /tmp/a           | diff -q - /tmp/r

결과:

  • 로컬 테스트 : 내 솔루션이 가장 빠르며 perl -0777 -F느립니다.
  • 온라인 에서 사용해보십시오! : 내 솔루션이 가장 빠르며 xxd느립니다.

참고 : diff출력이 동일해야하므로 모든 솔루션에 대해 실행 시간 이 동일해야합니다.


1
perl것을 삭제했습니다 . 당시에는 reverse문자열을 뒤집을 수도 있다는 것을 알지 못했기 때문에 분할하는 것이 의미가 없으며 버전이 훨씬 좋습니다.
Stéphane Chazelas

1

나는 다음을 시도했다.

tac -rs '.' input.gnp > output.png

아이디어는 문자를 구분 기호로 사용하여 'tac'을 강제하는 것입니다. 바이너리 파일에서 시도했지만 작동하는 것처럼 보였지만 확인을 부탁드립니다.

주요 이점은 파일을 메모리에로드하지 않는다는 것입니다.


tac입력에 줄 바꿈 문자가 포함되어 있으면 (여기서는 GNU 8.28에서) 작동하지 않습니다 . 대신 printf '1\n2' | tac -rs . | od -vAn -tc출력 . 멀티 바이트 문자 가 필요 하거나 일치 할 수도 있습니다 . \n 2 12 \n 1LC_ALL=C.
Stéphane Chazelas

4
LC_ALL=C tac -rs $'.\\|\n'그래도 작동하는 것 같습니다.
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.