bash 변수에 명령의 파일 출력을 저장합니다.

bash 변수에 명령의 파일 출력을 저장합니다.

동시에 다른 파일 foo에 쓰는 유틸리티가 있다고 가정해 보겠습니다 . n각 파일에는 서로 다른 데이터가 기록됩니다. 파일에 기록되는 내용은 미리 알 수 없습니다. 예를 들어 유틸리티는 다음과 같이 호출할 수 있습니다.

foo file_1 file_2 ... file_n

파일에 작성된 내용을 bash 변수에 저장하고 싶습니다. 물론, 유틸리티가 파일 시스템의 실제 파일에 쓴 다음 그 파일에서 읽도록 할 수도 있습니다.

foo file_1 ... file_n

output_1="$(cat file_1)"
...
output_n="$(cat file_n)"

rm file_1 ... file_n

다만, 파일 시스템을 건너뛰고 임시 파일 생성을 피하는 것이 더 효율적이지 않을까 생각합니다. 이것이 어떻게 달성될 수 있습니까? 이 목적으로 명명된 파이프를 사용할 수 있습니까?

ベストアンサー1

이제 답을 찾은 것 같아요. @terdon 솔루션의 문제점은 @ilkkachu가 언급했듯이 파일이 순차적으로 작성된다고 가정한다는 것입니다. 먼저 file1완료될 때까지 읽은 다음 계속 읽습니다 file2. 그러나 와 동시에 foo쓰기 는 가능하며 , 리더기가 부착되어 있지 않아 차단됩니다.file1file2file2

이 문제는 호출 직후 읽기 위해 각 FIFO를 열고 foo순차적으로 읽으면 해결될 수 있습니다. 그러나 이는 foo쓰기가 FIFO 버퍼 크기를 초과하지 않는 경우에만 작동합니다.

따라서 각 파일/fifo를 동시에 읽어야 합니다. 각 fifo에 대해 백그라운드에서 실행되고 완료될 때까지 fifo에서 데이터를 읽는 하위 쉘을 만들 수 있습니다. 그런 다음 서브쉘은 내용을 stdout으로 인쇄합니다. 따라서 FIFO에 기록된 데이터에 대한 버퍼 역할을 합니다.

# assume files don't exist yet
mkfifo "$@"

# opens fifos as writing
foo "$@" &

# for each fifo, create background subshell that reads from it
i=0
for file in "$@"; do
    exec {fd}< <(echo "$(cat $file)")
    fds[$i]=$fd
    (( i++ ))
done

# fifos are now fully connected
# consume content buffered in subshells
i=0
for file in "$@"; do
    file_contents[i]="$(cat <&${fds[$i]})"
    (( i++ ))
done

for (( i=0; i<${#file_contents[@]}; i++)); do
  printf "The contents of file number %d are: %s\n" "$(( $i+1 ))" "${file_contents[$i]}"
done

おすすめ記事