Bash: 출력을 수신하는 프로세스가 종료되면 eval을 종료하는 방법

Bash: 출력을 수신하는 프로세스가 종료되면 eval을 종료하는 방법

내 Ubuntu 컴퓨터에는 다음 줄이 포함된 보기 흉한 bash 스크립트가 있습니다.

search_command="find -L $(printf "%q" "$search_folder") \( ! -regex '.*/\..*/..*' \) -mindepth 1 2> /dev/null"
for i in "${IGNOREENDINGS[@]}"
do
    search_command="$search_command -not -name \"*$i\""
done
search_command="$search_command | sed 's|^${search_folder}/\?||'"
choice=$(eval "$search_command"|fzf -q "$file_query" -1 --preview "preview $search_folder {}")

fzf이 스크립트를 사용하면 명령 일치를 사용하여 파일을 선택할 수 있습니다 GNU find.

여기에는 다음과 같은 문제가 있습니다. 스크립트 인터페이스에서 파일을 선택하자마자 fzf 인터페이스가 닫히므로 완료된 것처럼 보이지만 여전히 명령이 완료될 fzf때까지 기다려야 합니다 (validation 포함 ). 장기. 왜 내가 원하는 파일이 거의 항상 즉시 나타나는지 잘 모르겠습니다.findtop

XY 문제를 피하기 위해 위에 몇 줄을 추가했습니다. 동일한 기능과 더 빠른 실행을 제공하는 모든 것이 만족스럽습니다.

답변1

여기에는 두 가지 가능성이 있습니다. fzf파일을 선택할 때 실제로 종료가 없거나 파일을 선택할 find때 종료가 없습니다 fzf. 후자인 경우 find종료할 때 수동으로 닫는 스크립트를 작성할 수 있습니다.fzf

Linux에서 파이프가 작동하는 방식은 find파이프에 쓰기를 시도하고 실패할 때까지 파이프가 파이프에서 아무것도 읽지 않는다는 사실을 알지 못합니다. 그래서 파일을 선택하면뒤쪽에 find찾고 있는 모든 것을 찾았으면 find파이프에 더 이상 쓰기가 수행되지 않으므로 종료하기 전에 전체 파일 시스템이 반복됩니다.

예를 들어, 임의의 파일을 생성한 /다음 실행하면 find / -name $random_file_name | head -n 1매우 빠르게 얻을 수 있는 모든 출력을 얻을 수 있지만 프로그램은 오랫동안 계속 실행됩니다.

이 문제를 해결하는 한 가지 방법은 프로세스가 완료되었을 때 프로세스를 직접 종료하는 것입니다. 특정 경우에 가장 쉬운 방법은 아마도 명명된 파이프일 것입니다.

tmp_fifo=`mktemp -u`
mkfifo "$tmp_fifo"
eval "$search_command" > "$tmp_fifo" &
choice="$(fzf -q "$file_query" -1 --preview "preview $search_folder {}" < "$tmp_fifo")" ; kill $!
rm "$tmp_fifo"

그러면 임시 명명된 파이프가 생성되고 거기에 find쓰고 fzf읽습니다. 그러나 fzf종료할 때 kill $!실행은 $!마지막으로 시작된 백그라운드 프로세스를 나타냅니다. 이 경우에는 find.

답변2

또 다른 대답좋아보이는데, FIFO를 관리해야 한다는게 단점이네요. 배쉬와 함께coprocFIFO의 이름을 지정하지 않고도 문제를 해결할 수 있습니다.

(참고: 이 답변이 특정 문제가 아닌 일반적인 문제를 해결하도록 하기 위해 변수 eval및 유사한 항목을 제거했습니다.)

coproc find ...         # this silently runs in background, no `&' nor explicit redirection needed
<&${COPROC[0]} fzf ...  # piping from `find' to `fzf'
kill $!                 # killing the last background process, i.e. `find'

관련 정보