次の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
このコンテキストで呼び出される前に閉じられた)が最新バージョンで修正されました。 Linuxで/dev/fd/x
bash 3.2を使用すると、同じ問題が発生します(実装が異なるため、他のエラーメッセージが表示されます)。
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
1 パイプが存在する場合、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