bash에서 스크립트가 실행될 때 변수 내용을 파일로 덤프합니다.

bash에서 스크립트가 실행될 때 변수 내용을 파일로 덤프합니다.

내 디렉토리에 많은 파일이 있습니다:

$ 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".

mkshFWIW, 이러한 "비로컬 인터럽트"는 또는 에서는 작동하지 않지만 , yash및 에서는 작동합니다.bashdashzshksh93

답변3

ls의 출력을 다른 프로그램의 입력으로 사용 하지 마십시오 . (신뢰성이나 안전의 개념을 포함하는 "작동"에 대한 정의에 대해) 작동하지 않으며 다음과 같은 문제가 있습니다.안 돼요셸의 와일드카드(예: 와일드카드 확장)가 오용으로 수행하려는 작업을 수행하므로 이 작업을 수행해야 합니다 ls.아니요구문 분석 ls(및 수행 방법)?.

비슷한 작업을 수행해야 하는 경우 대신 find ... -exec {} +or를 사용하세요 . 둘 중 하나가 실제로 작동하며 파일 이름에 어떤 문자가 있든 안전하게 작동합니다.find ... -print0 | xargs -0r ...ls

루프 for는 다음과 같이 작성되어야 합니다.

for file in *; do
  ...
done

루프 내부의 각 루프에 대해 다른 작업을 수행 for하려는 경우가 아니면 루프가 필요하지 않습니다 .$file

다음은 for 루프 작업을 수행하고 의 출력을 md5sum이름이 지정된 배열에 저장한 hashes다음 인쇄하는 몇 가지 대체 방법입니다.

  1. 사용 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쉘 변수의 값으로 정의됨)로 분할하고 각 "단어"를 배열의 별도 요소에 넣습니다.

  2. 사용 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
}

그러나 여기서는 함정조차 필요하지 않습니다. md5sumwith는 tee원하는 것을 수행합니다. 즉, $hashesAND 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) 옵션을 사용합니다 .md5sumhashes.txt

참고: 문자열 끝에는 항상 추가 빈 줄이 있으므로 $hashes줄 수가 1씩 늘어납니다. 배열을 사용할 때는 이런 일이 발생하지 않습니다.

관련 정보