脚本:
#!/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/file で機能します)。PS
verbose は、xclip がデーモン化されないようにするために使用されます。
答え1
&>
はバシズムなので、>/dev/null 2>&1
POSIXシェルでは に変更する必要があります。
答え2
[この回答はスクリプト内の非同期パイプラインに関するものです。廃止された&>
bash演算子と、>output 2>&1
代わりに常に使用する必要がある理由については、廃止された非推奨の構文]
#! /bin/sh cat "${1:-/dev/stdin}" | ... &
&
ここでは、スクリプトから、つまりジョブ制御が無効になっているシェルから開始され、非同期で実行されるパイプラインがあります ( によって終了されたため)。
による標準:
command1 & [command2 & ... ]
明示的なリダイレクトが実行される前に、非同期リストの標準入力は、 と同じプロパティを持つファイルに割り当てられているものとみなされます
/dev/null
。
問題はdash
、、、、などksh
が「非同期リスト」をパイプラインを含む任意のコマンドとして解釈し、 からの最初のコマンドの stdin をリダイレクトすることです。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
元の stdin が tty の場合にのみリダイレクトされ、他の種類のファイルの場合はリダイレクトされません。
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/tty
/dev/null
$ zsh -c 'readlink /proc/self/fd/0 &' </dev/zero
/dev/zero
すべてのシェルで機能する回避策は、stdin を別のファイル記述子に複製し、そこから最初のコマンドの stdin をリダイレクトすることです。
#! /bin/sh
exec 3<"${1:-/dev/stdin}"
cat <&3 | timeout 30 xclip -i -selection clipboard -verbose -r >/dev/null 2>&1 &