3

編集者注:この質問は、問題の性質を変更するいくつかの改訂を受けており、古いコメントや回答が無効になる可能性があります。元のタイトルは「Bash 出力を /dev/null にリダイレクトできません」でした。

サイレント モードを実装したい小さな Bash スクリプトを作成しようとしています。-v基本的に、デフォルトでほとんどの出力を非表示にし、で実行した場合に備えて、すべての出力を表示したいと思います。

したがって、スクリプトの冒頭に次のように記述しました。

#!/bin/bash
declare output=''
if [ "$1" = -v ]; then
  output="&1"
else
  output="/dev/null"
fi

次に、スクリプトに次のものがあります。

{
  # whatever commands...
} > $output 2>&1

サイレントモードはうまく機能します。ただし、詳細モードを試すと、&または(変数&1に基づいて) という名前のファイルが作成されます。outputまた、ファイルは空です。これは望ましい結果ではありません。出力を端末に残しておきたいのです。

これはリダイレクトの順序によるものですか、それとも私の変数が間違っているのでしょうか? "&1"編集:出力値をに置き換えることで、スクリプトが完全に機能するようになりました"/dev/tty"

4

2 に答える 2

0

tl;dr

  • ファイル記述子&1あなたの場合)へのリダイレクトを変数に保存することはできません-そうする場合、代わりにその名前でファイルを作成します(&1あなたの場合は文字通り名前が付けられたファイル)。

  • に設定$outputすると、常に端末に出力され、詳細な出力をファイルにキャプチャできなくなる/dev/ttyため、に設定することはお勧めできません。たとえば、動作しません。script -v > file

  • コメントからgniourf_gniourf アドバイスを受けて、exec代わりに使用します:exec > /dev/null 2>&1または、Bash 固有の構文を使用しexec &>/dev/nullて、スクリプトの残りの部分を沈黙させます。


ファイル記述子へのリダイレクトのみが機能します。

  • リダイレクト先が変数参照ではなくリテラルの場合。
  • とターゲットの間にスペースがない場合。>
date > &1 # !! SYNTAX ERROR: syntax error near unexpected token `&'

date >&1  # OK - but works with a *literal* `&1` only

variableを使用する場合、変数の内容は常にファイル名&1として解釈されるため、それは問題ではありません。そのため、構文エラーは発生しませんでしたが、代わりに文字通り名前が付けられた出力ファイルが作成されました。

output='&1'
date >$output  #  !! Creates a *file* named '&1'.
date > $output #  !! Ditto.

あなたの問題を解決するには、コメントからgniourf_gniourf のアドバイスを参考にすることをお勧めします:exec代わりに:

#!/usr/bin/env bash

if [[ $1 == '-v' ]]; then
  : # verbose mode: redirect nothing
else 
  # quiet mode: silence both stdout and stderr
  exec &>/dev/null
fi

echo 'hello'      # will only print with -v specified
echo 'hello' >&2  # ditto
于 2016-02-22T15:01:29.523 に答える