찾기 | xargs shasum은 체크섬 파일 자체의 체크섬을 조기에 생성하고 검사 할 때 실패합니다 sha1) 파일은 동일한 디렉토리에 있어야합니다. ~/test파일 f1과

내 문제 (와의 스크립트에서 #!/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 합계를 계산합니다 (maxdepth는 나중에 변경 될 수 있음). 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마지막 합계를 저장할 때 추가 파일 수정의 명백한 문제 때문에 나중에 실패합니다 .

나는 주변을 둘러보고 -pfor 플래그를 사용 xargs하여 find 명령을 실행하기 전에 어떻게 든 출력 파일을 생성한다는 것을 알았습니다. 따라서 추가 파일이 발견되어 체크섬됩니다 …

해결 방법으로 체크섬을 다른 위치 (temp 디렉토리를 통해 mktemp)에 저장하거나 구체적으로 찾기에서 제외시킬 수는 있지만 그것이 어떻게 작동하는지 왜 이해하고 싶습니다. 예를 들어 첫 번째 명령으로 출력 파일이 이미 디스크에 있는지 확인하면 정답을 얻지 못할 것입니다 …



답변

다음을 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'이 필요 --없고 -파일에 문제가 없었을 것 입니다.


답변

을 사용하고 있기 때문에 -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

이러한 모든 접근 방식에는 공백, 줄 바꿈 또는 기타가 포함 된 파일 이름을 포함하여 임의의 파일 이름을 사용할 수 있다는 이점이 있습니다.


답변

zsh:

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

경로 재 지정이 수행되기 전에 글로브가 확장되므로 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

라는 파일의 잠재적 인 문제를 피하기 위해 ./*대신 사용 하는 것이 좋습니다 .*-


답변

다른 답변에서 이미 언급했듯이 문제는 sums.sha1파이프 라인을 실행하기 전에 셸이 파일을 열고 만듭니다 . 많은 배포판 패키지의 sponge일부인 프로그램 을 사용할 수 있습니다 moreutils. 셸 리디렉션과 달리 sponge파일을 열기 전에 모든 것을받을 때까지 기다립니다. 일반적으로 동일한 파이프 라인에서 읽은 파일을 쓰려고 할 때 사용됩니다.

귀하의 경우 다음과 같이 사용됩니다 :

$ find -maxdepth 1 -type f -printf '%P\n' |xargs shasum |sponge sums.sha1
$ cat sums.sha1
31836aeaab22dc49555a97edb4c753881432e01d  B
7d157d7c000ae27db146575c08ce30df893d3a64  A


답변

find / xargs 등의 대안으로 sha1deep을 원할 수 있습니다. 그것은 아마도 다른 패키지에있을 것입니다-내 상자에는 md5deep 패키지가 있습니다.

다른 사람들이 말했듯이 sums.sha1은 찾기가 시작되기 전에 쉘에 의해 생성됩니다. 와 트릭 ! -name sums.sha1에는 find의지로 작동합니다

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


답변