
다음 bash-fu 코드는 Linux에서는 잘 작동하지만 MacOS에서는 작동하지 않습니다.
files="foo bar"
echo PROG 1
for file in $files
do
echo $file | tee -a tempfile.txt
done
sort -u tempfile.txt
echo PROG 2
function trick {
for file in $files
do
echo $file | tee -a $1
done
}
trick >(sort -u)
오류는 다음과 같습니다
PROG 1
foo
bar
bar
foo
PROG 2
tee: /dev/fd/63: Bad file descriptor
foo
tee: /dev/fd/63: Bad file descriptor
bar
Linux에서는 오류 없이 PROG 2
동일한 줄을 작성합니다 . PROG 1
MacOS에서는 파이프 핸들이 닫혀 있거나 상속되지 않은 것 같습니다.
위의 내용은 문제 재현을 위해 최소화된 샘플입니다. 실제로 저는 연결 출력과 리디렉션된 핸들을 모두 많이 처리합니다. 뭔가의 정신으로
function trick {
for file in $files
do
echo $file | tee -a $1 | grep -Eo "^.."
done
}
trick >(sort -u | sed 's|o|x|g')
코드는 Bash 4.1에서는 작동하지 않지만 여러 배포판(Arch, Ubuntu 및 Debian)의 Bash 4.4에서는 작동합니다.
답변1
macOS에는 매우 오래된 버전의 bash
. 해당 버그(해당 컨텍스트에서 호출하기 전에 해당 프로세스 대체에 대한 파일 설명자가 닫히는 것 tee
) 1이 최신 버전에서 수정되었습니다. /dev/fd/x
bash 3.2를 사용하면 Linux에서도 동일한 문제가 발생합니다(다른 방식으로 구현된 것과 다른 오류 메시지 포함 ).
zsh
여기에서는 대신에 or 을 사용할 수 있습니다 ksh93
. bash
어쨌든 여기를 피하는 것이 좋습니다 .프로세스 대체에서 프로세스를 기다리지 않습니다.(zsh는 그들을 기다리고, ksh93은 wait
그들을 대신하도록 지시받을 수 있습니다).
최신 버전(작성 당시 4.4.12)에도 bash
여전히 다음과 같은 몇 가지 버그가 있습니다.
$ bash -c 'eval cat <(echo test)'
test # OK but:
$ bash -c 'eval "echo foo;cat" <(echo test)'
foo
cat: /dev/fd/63: No such file or directory
$ bash -c 'eval f=<(echo test) "; cat \$f"'
cat: /dev/fd/63: No such file or directory
일부는 여전히 다음과 같은 파이프에 의해 트리거됩니다.
$ cat file
echo "$1"
cat "$1"
$ bash -c 'source ./file <(echo test)'
/dev/fd/63
test # OK but:
$ cat file2
echo "$1" | wc -c
cat "$1"
$ bash -c 'source ./file2 <(echo test)'
11
cat: /dev/fd/63: No such file or directory
¹ bash는 파이프라인이 있는 즉시 해당 파일 설명자를 닫습니다. 더 짧은 재생산:
$ bash -c 'f() { :; cat "$1"; }; f <(echo OK)'
OK
$ bash -c 'f() { :|:; cat "$1"; }; f <(echo test)'
cat: /dev/fd/63: No such file or directory