찾기 | xargs shasum은 체크섬 파일 자체의 체크섬을 (조기) 생성하고 검사에 실패합니다.

찾기 | xargs shasum은 체크섬 파일 자체의 체크섬을 (조기) 생성하고 검사에 실패합니다.

내 문제(가 포함된 스크립트 #!/bin/sh)는 다음과 같습니다. 보관을 위해 디렉터리의 모든 파일을 체크섬하려고 합니다. 모든 파일 이름의 체크섬(내 경우에는 sha1)을 포함하는 파일은 동일한 디렉터리에 있어야 합니다. ~/test파일 f1과 :을 포함하는 디렉토리가 있다고 가정합니다 f2.

mkdir ~/test
cd ~/test
echo "hello" > f1
echo "world" > f2

이제 체크섬을 계산해 보세요.

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum

정확히 내가 원하는 것은 현재 디렉터리의 모든 파일을 나열하고 sha1 합계를 계산하는 것입니다(최대 깊이는 나중에 변경될 수 있음). STDOUT의 출력은 다음과 같습니다.

f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2

안타깝게도 파일로 저장하려고 하면

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum > sums.sha1

생성된 파일에는 자체 체크섬이 표시됩니다.

da39a3ee5e6b4b0d3255bfef95601890afd80709  sums.sha1
f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2  

shasum --check따라서 마지막 금액을 저장할 때 추가 파일 수정에 명백한 문제가 있기 때문에 나중에 실패합니다 .

주위를 둘러보고 -p플래그를 사용하여 xargsfind 명령을 실행하기 전에 출력 파일을 생성하여 추가 파일을 찾아 체크섬하는 것을 발견했습니다.

해결 방법으로 체크섬을 다른 위치(임시 디렉토리를 통해 mktemp)에 저장하거나 찾기에서 특별히 제외할 수 있다는 것을 알고 있지만, 왜 그렇게 작동하는지 이해하고 싶습니다. 유용하지 않은 것 같습니다. 예를 들어 첫 번째 명령이 출력 파일이 이미 디스크에 있는지 확인하는 경우 정답을 얻지 못합니다.

답변1

다음을 사용하여 파일이 도착하는 것을 방지할 수 있습니다 xargs.

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' |
  xargs -r shasum -- > sums.sha1

공백, 개행, 따옴표 또는 백슬래시가 포함된 파일 이름과 관련된 문제를 방지하려면 다음을 사용합니다.

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' |
  xargs -r0 shasum -- > sums.sha1

대신에.

이는 으로 --시작하지 않기 위한 것 입니다 -. 그러나 -.-print0-printf '%P\0'---

답변2

당신이 사용하고 있기 때문에 -maxdepth 1재귀를 원하지 않는다고 가정합니다. 그렇다면 쉘에서 실행하십시오.

for f in ~/test/*; do
    shasum -- "$f"
done > sums.sha1

디렉터리를 건너뛰려면 다음을 수행할 수 있습니다.

for f in ~/test/*; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

재귀가 정말 필요하고 이를 사용하고 있다면 bash다음을 수행하십시오.

shopt -s globstar
for f in ~/test/**; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

이러한 모든 방법에는 공백, 줄 바꿈 또는 기타 항목이 포함된 임의의 파일 이름으로 작업할 수 있다는 이점이 있습니다.

답변3

그리고 zsh:

shasum -- *(D.) > sums.sha1

glob은 리디렉션 전에 확장되므로 sums.sha1처음에 존재하지 않으면 포함되지 않습니다.

D도트 파일(숨겨진 파일)입니다 find. .일반 파일(예: 귀하의 파일)만 선택하는 것입니다 -type f.

어쨌든 sums.sha1처음에 존재하는 경우를 제외하려면 다음을 수행하십시오.

setopt extendedglob # best in ~/.zshrc
shasum -- ^sums.sha1(D.) > sums.sha1

달리고 있는 분들은 참고하세요하나shasum 명령을 사용하므로 목록이 큰 경우 "Arg list too long" 오류가 표시될 수 있습니다. 이 문제를 해결하려면:

autoload zargs
zargs -e/ -- *(D.) / shasum > sums.sha1

라는 이름을 피하는 ./*것보다 사용하는 것이 좋습니다 .*-

답변4

find/xargs 등의 대안으로 sha1deep을 원할 수도 있습니다. 하지만 다른 패키지에 있을 수도 있습니다. 내 상자에는 md5deep 패키지에 있습니다.

다른 사람들이 말했듯이 sums.sha1은 find가 시작되기 전에 쉘에 의해 생성됩니다. ! -name sums.sha1to를 사용하는 트릭은 will find처럼 작동합니다.

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum | grep -v ' sums\.sha1$' > sums.sha1

관련 정보