명명된 파이프에서 한 줄씩 읽고 종료하는 방법은 무엇입니까?

명명된 파이프에서 한 줄씩 읽고 종료하는 방법은 무엇입니까?

난독화된 파일 오프너로 사용하고 싶은 다음 bash 스크립트가 있습니다. fifo를 생성하고, fzf를 실행하는 새 터미널을 생성하고, fzf의 출력을 fifo로 리디렉션합니다. 그런 다음 fifo에서 읽고 파일을 여는 함수를 호출합니다.

내 문제는 함수 내부의 while 루프가 open끝나지 않는다는 것입니다. 모든 행을 읽은 후 FIFO를 닫는 방법은 무엇입니까?

#!/usr/bin/env bash

FIFO=/tmp/fuzzy-opener
[ -e "$FIFO" ] || mkfifo "$FIFO"
exec 3<> "$FIFO"

function open {
  while read file; do
    # open every $file based on its mime-type
  done <&3
  echo 'done' # this is never reached
}

alacritty -e sh -c "fzf -m >&3" \
  && open

답변1

read()쓰기 끝이 닫히면 파이프에 EOF가 표시됩니다(0바이트 읽기에서 반환). 하지만 내 생각엔 <>파이프가 읽기-쓰기 모드로 열렸기 때문에 파이프에는 항상 작성자가 있고 셸은 파일 핸들을 열어둔 상태로 유지된다는 것입니다.

나는 쉘에서 파이프를 여는 것을 건너뛰고 다음을 수행할 수 있어야 한다고 생각합니다.

alacritty -e sh -c "fzf -m >$FIFO" && open < "$FIFO"

또는 더 적절하게는 다음과 같습니다.

alacritty -e sh -c 'fzf -m >"$1"' sh "$FIFO" && open < "$FIFO"

여기서는 질문의 구성이 다르게 작동한다고 가정합니다. 민첩성이 백그라운드에서 터미널을 생성하고 즉시 종료되는 경우에는 그렇게 해야 합니다. 그렇지 않은 경우 alacritty -e sh ... & open < "$FIFO"두 부분을 동시에 실행 해야 합니다 .

답변2

다음과 같은 이유로 몇 가지 대안을 제안합니다.

  • 귀하의 질문에 있는 스크립트에 따르면 FIFO가 실제로 필요하지 않은 것 같습니다.
  • 원칙적으로 Bash를 사용하고 있으므로 NUL 문자를 구분 기호(POSIX 파일 경로에서 허용되지 않는 유일한 바이트)로 활용할 수 있지만 불행히도 fzf개행 문자가 포함된 파일 이름에는 작동하지 않는 것 같습니다.
  • 파일에서 읽으면 /tmp심각한 보안 문제가 발생할 수 있습니다. 다른 사람이 파일을 /tmp/fuzzy-opener일반 파일로 만든 경우 스크립트가 open해당 내용에 기꺼이 적용됩니다(일부 시스템에서는 자신이 소유하지 않은 단어 쓰기 가능한 고정 파일에서 열림). ) exec 3<>will 디렉토리를 사용하세요오류 제기).

당신은 그것을 사용할 수 있습니다 :

function open {
  while IFS= read -r -d '' file
  do
    echo "$file"    # Replace with the actual open action
  done
}

alacritty -e sh -c 'fzf -m --disabled --print0 >&3' 3>&1 | open

-d ''제거하고 이식 가능하게 만들어 이식 가능하게 만들 수 있습니다 --print0(위의 제한 사항을 고려할 때 아무것도 손실되지 않습니다 fzf). 또는 배열을 사용하여 선택한 파일 이름을 저장합니다.

function open {
  for file
  do
    echo "$file"    # Replace with the actual open action
  done
}

mapfile -t -d '' toopen < <(alacritty -e sh -c 'fzf -m --print0 >&3' 3>&1) &&
  open "${toopen[@]}"

fzf두 경우 모두, 리더 명령이 연결된 파이프의 쓰기 끝을 복사하여 얻은 새 파일 설명자로 출력이 리디렉션된다는 점이 중요합니다 .

관련 정보