파일이 너무 많아서 체크섬을 확인해야 합니다. 다음과 같은 텍스트 파일이 있습니다.
체크섬 <tab>
파일 이름<new line>
나는 이것을 쉘 스크립트를 개선하기 위한 연습으로 사용할 수 있다고 생각했습니다. 이것이 제가 생각해낸 것이고 효과가 있었습니다. 더 좋은 방법이 있는지 궁금했습니다. 유연성이 별로 없다는 것을 알고 있습니다(예: 파일 형식과 알고리즘이 256이라고 가정). 하지만 피하려고 노력하고 있어요 cat
... echo
:)
감사해요!
#!/bin/sh
workingDir="/path/to/directory/"
textFile="checksums.txt"
filePath="$workingDir$textFile"
while read a b; do
shasumOutput=$(/usr/bin/shasum -a 256 "$workingDir$b" | /usr/bin/awk '{ print $1 }')
if [ "$a" = "$shasumOutput" ]; then
/usr/bin/printf "$b checksum matches: "$a", "$shasumOutput"\n"
else
/usr/bin/printf "$b checksum doesn't match: "$a", "$shasumOutput"\n"
fi
done < "$filePath"
답변1
~처럼고후가 지적했다shasum
귀하의 의견에는 해당 플래그에 대해 이미 완료된 확인을 복사하고 있습니다 -c
.
입력은 shasum -c
결과 콘텐츠여야 합니다 shasum
.
이것을 무시하십시오 ...
귀하의 스크립트는 좋아 보이지만 일부에 대해 언급할 수 있습니다.
이 줄은 예를 들어 대신 printf
에 로 작성하는 것이 더 좋습니다.printf 'format string' "$var1" "$var2" "etc."
/usr/bin/printf "$b checksum matches: "$a", "$shasumOutput"\n"
사용
printf '%s checksum matches: %s, %s\n' "$b" "$a" $shasumOutput"
사용의 요점 printf
은 정적 형식 문자열과 형식 문자열 템플릿에 들어가는 몇 가지 변수 데이터가 있다는 것입니다.
또한 $( shasum ... )
외부 유틸리티에 대한 호출 수를 피하고 줄이기 위해 다음을 수행합니다.
#!/bin/sh
checkdir='/some/path'
checkfile="$checkdir/checksums.txt"
while read -r checksum filename; do
if [ ! -f "$checkdir/$filename" ]; then
printf 'Not found: %s\n' "$filename"
continue
fi
gsha256sum "$checkdir/$filename" | {
read -r realsum name
if [ "$realsum" != "$checksum" ]; then
printf 'Mismatch for "%s":\n\t%s != %s\n' \
"$filename" "$checksum" "$realsum"
else
printf '%s OK\n' "$filename"
fi
}
done <"$checkfile" >&2
이렇게 하면 외부 유틸리티 호출(대부분의 셸에서) 수가 단 한 번(SHA256 유틸리티)으로 줄어듭니다.
내 OpenBSD 시스템에서 SHA256 체크섬을 생성하는 GNU coreutils 유틸리티는 gsha256sum
. 나는 그 출력이 shasum -a 256
귀하의 시스템과 동일하다고 가정합니다.
몇 가지 참고사항:
/
나는 보통 디렉토리 이름 끝에 넣지 않습니다 . 대신 변수를 사용할 때 구분 기호를 삽입합니다. 이렇게 하면 이것이$checkdir/checksum.txt
파일에 대한 경로라는 것을 직접 볼 수 있지만${checkdir}checksum.txt
(또는 이와 유사하게) 더 모호합니다.체크섬을 확인하기 전에 파일이 실제로 존재하는지 확인합니다.
SHA256을 구문 분석하는 프로그램의 출력을 사용하는 대신
awk
체크섬 파일에서 체크섬과 파일 이름을 읽는 것과 같은 방식으로 읽습니다. 나는 상황에 따라 이 작업을 수행합니다{ ...; }
.나는 치료 중이야모두루프의 출력은 "진단 메시지" 역할을 하며
>&2
이후에 모든 메시지를 표준 오류로 리디렉션하는 데 사용됩니다done
.나는 실제적인 이유가 없는 한 스크립트에서 유틸리티에 대한 절대 경로를 사용하지 않는 경향이 있습니다. 예를 들어, 유틸리티는 거의 항상 셸에 내장되어 있으며 이를 명시적으로 사용할
printf
이유가 거의 없습니다 ./usr/bin/printf
입력 파일의 모든 파일 이름을 사용하여 SHA256 유틸리티를 호출한 다음 해당 호출의 체크섬을 비교하여 SHA256 유틸리티를 한 번(또는 아주 적은 호출) 호출할 수 있지만 코드는 아마도 좀 더 복잡할 것입니다. 작업량이 엄청날 것이다. 이것이 일회성 작업이고 입력 파일이 그다지 크지 않다면 그럴 가치가 없습니다.