パイプがファイルの終わりを待つか、エラーの後に停止するようにするにはどうすればよいですか?

パイプがファイルの終わりを待つか、エラーの後に停止するようにするにはどうすればよいですか?

視聴後、次のコマンドを試しました。この動画配管いたずらについて。

man -k . | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf | zathura -

デフォルトでは、ユーザーがそのいずれかを選択できるようにmanページリストをdmenuに印刷し、xargsを使用して実行しman -Tpdf %(xargsの入力時にマニュアルページのgitのpdfをstdoutとして印刷します)pdfリーダー(zathura)。

問題は、(ビデオでわかるように)dmenuでマンページを選択する前にPDFリーダーが起動することです。 「Esc」をクリックして「なし」を選択すると、PDFリーダーが開いたままになり、文書はまったく表示されません。

PDFリーダー(およびパイプラインチェーン内の他のコマンド)が入力がファイルの終わりに達したとき、または入力が受信されたときにのみ実行されるようにするにはどうすればよいですか?または、リンクされたコマンドの1つがゼロ以外の終了ステータスを返した後にパイプラインチェーンを停止するにはどうすればよいですか? (したがって、オプションが選択されておらず、dmenuがエラーを返した場合、次のコマンドは実行されません.)

答え1

PDFリーダー(およびパイプラインチェーン内の他のコマンド)が入力がファイルの終わりに達したとき、または入力が受信されたときにのみ実行されるようにするにはどうすればよいですか?

持つifnemoreutils(Debianではパッケージにあります):

ifne標準入力が空でない場合にのみ、次のコマンドを実行します。

あなたの場合:

… | ifne zathura -

答え2

PDFファイルは検索可能でなければなりません。すべてのPDFビューアは最初にトレーラーを見てからそこから外部参照テーブルのオフセットに移動する必要があります。

パイプを取得できないため、zathuraすべての入力を一時ファイルにコピーし、その一時ファイルを通常使用する難読化トリックが使用されます。この「賢い」トリックは間違った希望を作り出し、人々がPDFファイルをストリーミングできると信じさせます。

しかし、とにかくzathura本当にする文書を表示する前にEOFを待ってください。このために何もする必要はありません。

(sleep 10; cat file.pdf) | zathura -
# will really show the content of file.pdf after 10 seconds

問題は、zathuraファイルが正常な場合にのみウィンドウを開き、ファイルが正常でない場合はエラーで終了するオプションがないことです。すべてが正常であるかのようにそのまま残ります。

$ dd if=file.pdf bs=50000 count=1 status=none | zathura -
error: could not open document  # its window still hanging around showing nothing

$ echo $?
0  # really?

したがって、出力を一時ファイルに直接リダイレクトし、すべてが正常な場合にのみ実行しても、何らかの理由で出力が気に入らないと、zathuraユーザーに黒いウィンドウが表示されないという保証はありません。zathura


さて、

man -X man

gxditview70年代から出てきたように見えますが、X11ウィンドウにマンページを表示します;-)

もちろん、いつでも次のものを使用できます。

... | xargs xterm -e man

他の多くの機能強化に加えて、検索と正しいテキストの選択に正規表現を使用できます。

答え3

パイプラインのすべてのコマンドはほぼ同時に開始されます。パイプのI / Oのみを同期できます。さらに、パイプはパイプバッファが許可するだけの情報を保持できます。

したがって、パイプラインステップの実行を避けることはできません。

  1. それにもかかわらず、このステップのコマンドは、他のすべてのステップの開始時に開始されます。
  2. コマンドがパイプラインを介して渡された入力を使用しない場合、パイプラインの最初の数ステップはブロックされます。

代わりに、パイプが完了するまで出力をファイルに書き込みます。次にファイルを使用します。

はい(パラメータが1つの関数):

myman () {
    tmpfile=$( mktemp )

    if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile" && [ -s  "$tmpfile" ]
    then
        zathura "$tmpfile"
    fi

    rm -f "$tmpfile"
}

zathuraパイプが失敗したxargs場合(部分的にゼロ以外の値を返す)、結果ファイルが空であってもプログラムは実行されません。

bashシェルでは、パイプがパイプで失敗した最初のコマンドの終了ステータスを返すように、pipefailシェルオプションを設定することもできます。変数をset -o pipefail作成したいと思います。tmpfilelocal

myman () {
    local tmpfile=$( mktemp )

    if [ -o pipefail ]; then
        set -o pipefail
        trap 'set +o pipefail' RETURN
    fi

    if man -k "$1" | dmenu -l 20 | awk '{print $1}' | xargs -r man -Tpdf >"$tmpfile"
    then
        zathura "$tmpfile"
    fi

    rm -f "$tmpfile"
}

pipefailまだ設定されていない場合は、関数期間のオプションを設定し、必要に応じて設定を解除します。-s出力ファイルのテストを削除します。

関連情報