파일의 마지막 바이트를 되돌리시겠습니까?

파일의 마지막 바이트를 되돌리시겠습니까?

타임스탬프를 수정하지 않고 파일 끝의 단일 바이트를 반전하여 해싱 프로그램을 테스트하고 싶습니다. 타임스탬프를 변경하지 않고 유지하는 것은 쉽지만 UNIX 유틸리티를 사용하여 파일의 마지막 바이트를 어떻게 되돌릴 수 있습니까?

예: 마지막 바이트를 0xFF로 XOR합니다(이 작업은 쉽게 되돌릴 수 있습니다).

답변1

sed는 아니지만 Perl에서는 작동하는 것 같습니다.

perl -pe 's/.\z/ $& ^ "\xff" /es if eof'  < in > out

한 줄씩 읽히지만 8비트이므로 문제가 되지 않습니다. eof마지막 줄에서 true이고 \z문자열의 원래 끝에서 일치합니다( $선택적 최종 개행 이전에도 일치하므로 엄격하게 마지막 바이트는 아님). 교체는 단순히 일치하는 문자열을 XOR합니다.

답변2

나는 Python을 사용하여 직접 해냈습니다.

python3 -c "import os, sys; name = sys.argv[1]; info = os.stat(name); f=open(sys.argv[1], 'rb+'); f.seek(-1,2); b = f.read(1)[0] ^ 0xFF; f.seek(-1,2); f.write(bytes([b])); print('Writing:', bytes([b])); os.utime(name, (info.st_atime, info.st_mtime))" filename

이것은 가장 우아한 해결책은 아니지만 여러분은 몇 가지 깔끔한 sed 트릭을 가지고 있고 더 잘할 수 있을 것이라고 확신합니다.

이것은 정식 버전입니다. ./invert.py(파일 이름)를 사용하여 실행할 수 있습니다.

import os, sys

name = sys.argv[1]
info = os.stat(name)

with open(name, 'rb+') as f:
    f.seek(-1,2)
    b = f.read(1)[0] ^ 0xFF
    f.seek(-1,2)
    f.write(bytes([b]))
    print('Writing:', bytes([b]))
    os.utime(name, (info.st_atime, info.st_mtime))

답변3

sed및 같은 도구는 awk일반적으로 파일을 찾거나 바이트 수준에서 파일 내용을 조작하는 데 적합하지 않습니다. 라인 지향적이며 주소로 정규 표현식이나 라인 번호가 필요하며 크기나 타임스탬프와 같은 파일의 메타데이터를 검색할 수 있는 (내장된) 방법이 없습니다.

명령줄 도구를 통해 원하는 결과를 얻는 것도 가능하지만, 내가 아는 한 어떤 경우에도 "접착" 작업을 수행해야 합니다.

이것은 단지 재미를 위한 나의 시도입니다 :(원하는 경우 시연을 위해 한 줄로)

(set -e -- $(ls -l <file>); pos=$(($5 - 1)); asciicode=$(od -j "$pos" -t u1 -A n "$9"); invcode=$(printf '%02x' $((asciicode ^ 0xff))); printf "\\x${invcode}" | dd of="$9" obs="$pos" seek=1)

<file>파일 이름으로 바꾸십시오 .

보시다시피 이것은 간단한 진술이 아닙니다. POSIX와 어느 정도 호환되도록 만들었지만, 그것 없이도 그다지 짧지는 않습니다.

또한 파일의 타임스탬프를 고려하지 않는다는 점에 유의하세요. 명령줄 도구를 사용하여 이 작업을 수행하려면 다음과 같습니다.(이번에는 가독성과 설명을 위해 분류되었습니다.)

(
set -e -- $(ls -l <file>)  # <-- parsing 'ls' output generally is not a good move
pos=$(($5 - 1))            # file's size from `ls -l`, minus 1 to point to last byte
asciicode=$(od -j "$pos" -t u1 -A n "$9")  # 'od' can seek with '-j' option
invcode=$(printf '%02x' $((asciicode ^ 0xff)))  # 8-bit value read by 'od' xor-ed
                                                # and made a 0-padded 2-digits hex value
temp="$(mktemp)"                               # temporary helper file
trap 'rm -f "$temp"' EXIT                      # dispose of it in due time
touch -r "$9" "$temp"                          # copy original file's timestamp
printf "\\x${invcode}" | dd of="$9" obs="$pos" seek=1  # put computed 8-bit value in place
touch -r "$temp" "$9"                          # restore file's timestamp
)

touch -r 나노초 정확도를 유지하는 가장 이식 가능한 방법이므로 임시 파일에서 이 방법을 앞뒤로 사용하십시오.

출력을 구문 분석 ls하는 위험한 작업을 수행해야 한다는 점을 알아두면 좋겠지만 파일 크기를 검색하는 다른 POSIX 도구는 생각할 수 없습니다. 물론 이 경우 더 안전한 방법으로 수행할 수 있지만(스크립트를 더 복잡하게 만듦) 이러한 필요성은 다시 표준 도구를 의도된 작업 이상으로 확장하고 있음을 시사할 수 있습니다.

관련 정보