내 문제(가 포함된 스크립트 #!/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
플래그를 사용하여 xargs
find 명령을 실행하기 전에 출력 파일을 생성하여 추가 파일을 찾아 체크섬하는 것을 발견했습니다.
해결 방법으로 체크섬을 다른 위치(임시 디렉토리를 통해 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.sha1
to를 사용하는 트릭은 will find
처럼 작동합니다.
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum | grep -v ' sums\.sha1$' > sums.sha1