
내 디렉토리에 많은 파일이 있습니다:
$ ls
file000001
file000002
# ... truncated ...
file999999
나는 이와 같은 파일의 md5sum을 계산하고 결국 파일에 덤프합니다.
hashes=''
for file in $(ls); do
hashes+=$(md5sum $file)
hashes+="\n"
done
echo "$hashes" > hashes.txt
이제 루프 내에서 스크립트를 실행하는 동안 Ctrl+C를 누르고 내용을 hashes.txt 파일에 덤프하고 for
싶습니다 . hashes
가능합니까?
(예, 각 파일에 대해 md5sum을 계산할 때마다 md5sum을 추가할 수 있지만 hahes.txt
그렇게 할 것입니다(위에 표시된 대로).)
위의 예제 코드는 끔찍합니다. 저는 실제로 md5sum을 예로 사용하고 있습니다. 내 질문의 목적은 실제로 Ctrl+C를 작동시키는 방법을 찾는 것입니다.
답변1
trap ctrl_c INT
ctrl_c() {
echo "$hashes" > hashes.txt
exit 0
}
ls
그런데, 나는 파일 목록을 얻는 데 사용하지 않지만 for file in *; do
.
답변2
trap break INT
루프 전:
hashes=
trap break INT
for file in *; do
hashes+=$(md5sum -- "$file")$'\n'
done
trap - INT
echo "$hashes" > hashes.txt
$(ls)
귀하의 스크립트( , ) 에서 의심스러운 부분을 수정했습니다 "\n"
.
mksh
FWIW, 이러한 "비로컬 인터럽트"는 또는 에서는 작동하지 않지만 , yash
및 에서는 작동합니다.bash
dash
zsh
ksh93
답변3
ls
의 출력을 다른 프로그램의 입력으로 사용 하지 마십시오 . (신뢰성이나 안전의 개념을 포함하는 "작동"에 대한 정의에 대해) 작동하지 않으며 다음과 같은 문제가 있습니다.안 돼요셸의 와일드카드(예: 와일드카드 확장)가 오용으로 수행하려는 작업을 수행하므로 이 작업을 수행해야 합니다 ls
.왜아니요구문 분석 ls
(및 수행 방법)?.
비슷한 작업을 수행해야 하는 경우 대신 find ... -exec {} +
or를 사용하세요 . 둘 중 하나가 실제로 작동하며 파일 이름에 어떤 문자가 있든 안전하게 작동합니다.find ... -print0 | xargs -0r ...
ls
루프 for
는 다음과 같이 작성되어야 합니다.
for file in *; do
...
done
루프 내부의 각 루프에 대해 다른 작업을 수행 for
하려는 경우가 아니면 루프가 필요하지 않습니다 .$file
다음은 for 루프 작업을 수행하고 의 출력을 md5sum
이름이 지정된 배열에 저장한 hashes
다음 인쇄하는 몇 가지 대체 방법입니다.
사용
printf
:$ hashes=( $( md5sum * ) ) $ printf '%s %s\n' "${hashes[@]}" > hashes.txt $ cat hashes.txt b026324c6904b2a9cb4b88d6d61c81d1 file.1 26ab0db90d72e28ad0ba1e22ee510510 file.2 6d7fce9fee471194aa8b5b6e47267f03 file.3
두 개의 형식 문자열은
%s
두 개의 공백으로 구분 됩니다printf
. 이것은 그 자체와 동일한 출력을 생성합니다md5sum
.그런데 다음을 사용하여 항목이 배열에 어떻게 저장되는지 확인할 수 있습니다
typeset -p
.$ typeset -p hashes declare -a hashes=([0]="b026324c6904b2a9cb4b88d6d61c81d1" [1]="file.1" [2]="26ab0db90d72e28ad0ba1e22ee510510" [3]="file.2" [4]="6d7fce9fee471194aa8b5b6e47267f03" [5]="file.3")
쉘은 출력을
md5sum
단어($IFS
쉘 변수의 값으로 정의됨)로 분할하고 각 "단어"를 배열의 별도 요소에 넣습니다.사용
tee
:$ hashes=( $( md5sum * | tee hashes.txt) ) $ cat hashes.txt b026324c6904b2a9cb4b88d6d61c81d1 file.1 26ab0db90d72e28ad0ba1e22ee510510 file.2 6d7fce9fee471194aa8b5b6e47267f03 file.3
이를 알면 Lasse Kliemann의 함정에 대한 답은 다음과 같이 쓸 수 있습니다.
trap ctrl_c INT
ctrl_c() {
printf '%s %s\n' "${hashes[@]}" > hashes.txt
exit 0
}
그러나 여기서는 함정조차 필요하지 않습니다. md5sum
with는 tee
원하는 것을 수행합니다. 즉, $hashes
AND hashes.txt
파일을 동시에 채웁니다.
또는 배열을 사용하지 않으려는 경우:
$ for file in *; do
hashes+="$(md5sum "$file" | tee -a hashes.txt)"$'\n'
done
$ echo "$hashes"
b026324c6904b2a9cb4b88d6d61c81d1 file.1
26ab0db90d72e28ad0ba1e22ee510510 file.2
6d7fce9fee471194aa8b5b6e47267f03 file.3
여기서는 루프에서 실행 중이고 반복할 때마다 파일을 덮어쓰는 것을 원하지 않기 때문에 tee
' -a
( --append
) 옵션을 사용합니다 .md5sum
hashes.txt
참고: 문자열 끝에는 항상 추가 빈 줄이 있으므로 $hashes
줄 수가 1씩 늘어납니다. 배열을 사용할 때는 이런 일이 발생하지 않습니다.