내 문제 (와의 스크립트에서 #!/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
마지막 합계를 저장할 때 추가 파일 수정의 명백한 문제 때문에 나중에 실패합니다 .
나는 주변을 둘러보고 -p
for 플래그를 사용 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