''cat "${1:-/dev/stdin} | ... &>/dev/null'' この bash では動作しますが、ダッシュでは動作しません。

''cat "${1:-/dev/stdin} | ... &>/dev/null'' この bash では動作しますが、ダッシュでは動作しません。

スクリプト:

#!/bin/sh
#
# reads stdin/file and copies it to clipboard
# clears it after 30s
#
cat "${1:-/dev/stdin}" | timeout 30 xclip -i -selection clipboard -r -verbose &>/dev/null &

stdinだけが動作しないことがわかります(bashを使用するとstdin /ファイルで動作します)。
PS verboseは、xclipがデーモンになるのを防ぐために使用されます。

答え1

&>bashismなので、>/dev/null 2>&1POSIXシェルに変更する必要があります。

答え2

[この回答は、廃止されたbash演算子の説明と、それを&>常に使用する理由についてです。>output 2>&1廃止され、廃止された構文]

#! /bin/sh
cat "${1:-/dev/stdin}" | ... &

&これには、スクリプトから始まり(によって終了したため)非同期的に実行されるパイプラインがあります。つまり、ジョブ制御が無効なシェルで開始されました。

~によると基準:

command1 & [command2 & ... ]

明示的なリダイレクトが行われる前の非同期リストの標準入力はあたかも/dev/null

問題はdashkshなどが「非同期リスト」をmksh任意yashのコマンド(パイプを含む)として解釈し、最初のコマンドの標準入力をリダイレクトすることです/dev/null

$ echo foo | dash -c 'cat | tr fo FO & echo DONE'
DONE
$ echo | dash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
/dev/null

ただし、bashこれを「簡単なコマンド」として解釈し、/dev/null実行時に標準入力のみをリダイレクトします。いいえパイプラインの一部:

$ echo foo | bash -c 'cat | tr fo FO & echo DONE'
DONE
FOO
$ echo | bash -c 'readlink /proc/self/fd/0 | cat & echo DONE'
DONE
pipe:[69872]
$ echo | bash -c 'readlink /proc/self/fd/0 & echo DONE'
DONE
/dev/null
$ bash -c 'cat | tr a A & echo DONE'
DONE
cat: -: Input/output error

zsh/dev/null他の種類のファイルではなくttyの場合にのみ、元の標準入力をリダイレクトします。

$ zsh -c 'readlink /proc/self/fd/0 &' </dev/tty
/dev/null
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/zero
/dev/zero

すべてのシェルで動作する解決策は、標準入力を別のファイル記述子にコピーし、そこから最初のコマンドの標準入力をリダイレクトすることです。

#! /bin/sh
exec 3<"${1:-/dev/stdin}"
cat <&3 | timeout 30 xclip -i -selection clipboard -verbose -r >/dev/null 2>&1 &

答え3

dashPOSIX標準として位置決めされています。 POSIXはリダイレクトのみを指定します[n]>。しかし、bash多くの独自の機能を紹介します。&>そのうちの1つで、出力記述子(stderrsum stdout)を表します。

あなたはについての記事を読む必要がありますクンと突進互換性。

たぶん助けを得るかもしれません。中断注意ユーティリティは、スクリプト内の特定の指示を見つけるのに役立ちますbash

関連情報