타임스탬프를 수정하지 않고 파일 끝의 단일 바이트를 반전하여 해싱 프로그램을 테스트하고 싶습니다. 타임스탬프를 변경하지 않고 유지하는 것은 쉽지만 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 도구는 생각할 수 없습니다. 물론 이 경우 더 안전한 방법으로 수행할 수 있지만(스크립트를 더 복잡하게 만듦) 이러한 필요성은 다시 표준 도구를 의도된 작업 이상으로 확장하고 있음을 시사할 수 있습니다.