シェルの制御およびリダイレクト演算子は何ですか?

シェルの制御およびリダイレクト演算子は何ですか?

さまざまなシンボルを使用してさまざまなコマンドをリンクするオンラインチュートリアルを頻繁に表示します。たとえば、

command1 |  command2
command1 &  command2
command1 || command2    
command1 && command2

他の人はコマンドをファイルにリンクするようです。

command1  > file1
command1  >> file1

これらは何ですか?名前は何ですか?彼らは何をしていますか?もっとありますか?


これは問題のメタスレッドです。

答え1

これをシェル演算子といい、その他にもあります。 2つの主要カテゴリのうち最も一般的なカテゴリを簡単に説明します。制御演算子そしてリダイレクト演算子、とbashシェルで動作する方法。

A. 制御演算子

POSIXの定義

シェルコマンド言語で制御機能を実行するタグ。
次の記号のいずれかです。

&   &&   (   )   ;   ;;   <newline>   |   ||

バッシュから|&

A!いいえ制御演算子ですが、予約語。論理NOT [否定演算子]になります。算術表現内部テスト構造(まだ空白の区切り文字が必要です)。

A.1 リスト終了者

  • ;: 最初のコマンドの結果に関係なく、他のコマンドが完了した後に 1 つのコマンドを実行します。

      command1 ; command2
    

まずcommand1、前景で実行し、完了するとcommand2実行されます。

文字列リテラルにないか、特定のキーワードの後に​​改行がありません。いいえセミコロン演算子と同じです。単純なコマンドの区切りリスト;はまだあります。リスト- シェルのパーサーと同様に、別の単純な;コマンドに従う単純なコマンドは実行前に読み取る必要があり、改行はコマンドのリスト全体またはリストのリストを区別できます。違いは微妙ですが複雑です。改行は、シェルが改行後のデータを読み取る前のコマンドがないと仮定し、シェルが読み取った単純なコマンドの評価を開始できる点を示しますが、セミコロンはそうではありません;

  • &:バックグラウンドでコマンドが実行されるため、同じシェルで作業を続けることができます。

       command1 & command2
    

ここではcommand1バックグラウンドで起動し、終了をcommand2待たずに直ちにフォアグラウンドで実行を開始しますcommand1

次の改行文字はcommand1オプションです。

A.2 論理演算子

  • &&:他のコマンドが正常に終了した場合にのみ、1つのコマンドを実行できるANDのリストを作成するために使用されます。

       command1 && command2
    

完了するとここで実行されますcommand2command1ただ成功した場合command1(終了コードが0の場合)、両方のコマンドはフォアグラウンドで実行されます。

このコマンドは次のように書くこともできます。

    if command1
    then command2
    else false
    fi

またはif command1; then command2; fi返品ステータスを無視してください。

  • ||:他のコマンドが終了しない場合にのみ、1つのコマンドを実行できるORリストを作成するために使用されます。

       command1 || command2
    

ここでは、command2失敗時にのみ実行されますcommand1(ゼロ以外の終了ステータスが返される場合)。どちらのコマンドもフォアグラウンドで実行されます。

このコマンドは次のように書くこともできます。

    if command1
    then true
    else command2
    fi

またはより短い方法でif ! command1; then command2; fi

&&とは||関連付けられていることに注意してください。シェル論理演算子&&および||の優先順位より多くの情報を知りたいです。

  • !:これは "not"演算子として機能する予約語です(ただし、区切り文字が必要です)。コマンドの戻り状態を否定するために使用されます。コマンドがゼロ以外の状態を返す場合は、ゼロを返します。状態0の場合は1を返します。プログラムロジックNOT 1を返すことも実用的ですtest

      ! command1
    
      [ ! a = a ]
    

算術式の実際のNOT演算子:

    $ echo $((!0)) $((!23))
    1 0

A.3 パイプラインオペレータ

  • |: あるコマンドの出力を別のコマンドの入力に渡すパイプ演算子です。パイプ演算子で作成されたコマンドが呼び出されます。管路

       command1 | command2
    

    印刷されたすべての出力command1はに入力として渡されますcommand2

  • |&2>&1 |:これはbashとzshの略です。あるコマンドの標準出力と標準エラーを別のコマンドの入力に渡します。

      command1 |& command2
    

A.4その他のリスト句読点

;;終了を表示するためにのみ使用されます。ケースステートメント。 Ksh、bash、zshは;&次のケースにジャンプし;;&(ATT kshではない)、後続のケースをテストし続ける機能もサポートします。

(そして)慣れてください。グループコマンドサブシェルから始めます。{および}グループコマンドを使用しますが、サブシェルで実行しないでください。バラよりこの回答シェル構文のさまざまな種類の括弧、角括弧、および中括弧について話し合います。

B. リダイレクト演算子

リダイレクト演算子のPOSIX定義

シェルコマンド言語でリダイレクト機能を実行するトークンです。次の記号のいずれかです。

<     >     >|     <<     >>     <&     >&     <<-     <>

これにより、コマンドの入力と出力を制御できます。単純なコマンド内でもコマンドの後にも表示できます。リダイレクトは、表示された順序で左から右に処理されます。

  • <:コマンドを入力します。

      command < file.txt
    

上記の内容はのcommand内容に従って実行されますfile.txt

  • <>:上記と同じですが、ファイルは次の場所で開きます。読み取り+書き込み代わりにパターン読み取り専用:

      command <> file.txt
    

ファイルが存在しない場合は生成されます。

この演算子はほとんど使用されません。なぜなら、コマンドは通常読むしかし、標準入力ではさまざまな特定の状況で役に立ちます。

  • >:コマンドの出力をファイルに送信します。

      command > out.txt
    

上記は出力をcommandout.txtファイルが存在する場合はその内容が上書きされ、ファイルが存在しない場合はファイルが生成されます。

この演算子はまた、何かを印刷するかどうかを選択するためによく使用されます。標準エラーまたは標準出力:

    command >out.txt 2>error.txt
 

上記の例では、>標準出力がリダイレクトされ、2>標準エラーがリダイレクトされます。リダイレクトされた出力を使用することも可能です1>が、これがデフォルト値なので、1一般的に省略して単純に>

したがって、これを実行しcommand、エラーメッセージと共にfile.txt出力を保存するには、次の手順を実行します。out.txterror.txt

    command < file.txt > out.txt 2> error.txt
  
  • >|::と同じですが、シェルが>上書きを拒否するように設定されていても(set -Cまたは使用set -o noclobber)ターゲットを上書きします。

      command >| out.txt
    

存在する場合out.txtの出力はcommandその内容を置き換えます。存在しない場合に生成されます。

  • >>:と同じです>が、ターゲットファイルが存在する場合は新しいデータが追加されます。

      command >> out.txt
    

out.txt存在する場合は、commandすでに存在する項目に出力を追加します。存在しない場合に生成されます。

  • >&:(POSIX仕様に従って)次に囲まれた場合数字1>&2)または-右(1>&-)リダイレクトのみ可能一つファイル記述子を削除または閉じます(>&-)。

>&ファイル記述子番号の後に続くのは、ファイル記述子をリダイレクトする移植可能な方法であり、ファイル>&-記述子を閉じる移植可能な方法です。

このリダイレクトの右側がファイルの場合は、次のトピックをお読みください。

  • >&&>および:(上記>>&参照&>>)標準エラーと標準出力をそれぞれ置換または追加してリダイレクトします。

      command &> out.txt
    

標準エラーと標準出力は両方commandに保存され、out.txt内容を上書きするか、内容がない場合は新しく作成されます。

    command &>> out.txt
 

上記と同じです。ただしout.txt、存在する場合の出力とエラーがcommand追加されます。

この&>亜種はbashcsh >&(数十年前)に由来しています。これらはすべて他のPOSIXシェル演算子と競合するため、移植可能なスクリプトには使用しないでくださいsh

  • <<:ここに文書があります。通常、複数行の文字列を印刷するために使用されます。

       command << WORD
           Text
       WORD
    

    ここでは、上記の例で次の項目が見つかるまですべてが入力として使用されcommandます。通常、またはそのバリアントですが、目的の英数字(単なる)文字列にすることができます。の一部が引用またはエスケープされると、ここの文書のテキストは文字通り処理され、拡張(変数など)は行われません。引用符なしで置くと、変数が拡張されます。詳細については、次を参照してください。WORDTextWORDEoFWORDバッシュマニュアル

    command << WORD ... WORD出力を別のコマンドに直接パイプするには、パイプを<< WORD終了するWORDの後ろまたは後ろの行ではなく、同じ行に配置する必要があります。たとえば、

       command << WORD | command2 | command3...
           Text
       WORD
    
  • <<<:ここの文字列はここのドキュメントに似ていますが、1行です。これは、Unixポートまたはrc(元の場所)、zsh、ksh、yash、およびbashの特定の実装にのみ存在します。

      command <<< WORD
    

与えられたすべてはWORD拡張され、その値はに入力として渡されますcommand。これは通常、変数の内容をコマンドに入力として渡すために使用されます。たとえば、

     $ foo="bar"
     $ sed 's/a/A/' <<< "$foo"
     bAr
     # as a short-cut for the standard:
     $ printf '%s\n' "$foo" | sed 's/a/A/'
     bAr
     # or
     sed 's/a/A/' << EOF
     $foo
     EOF

他の演算子(>&-、、x>&y x<&y)を使用してファイル記述子を閉じたりコピーしたりできます。これについての詳細は、シェルマニュアルの関連セクション(ここ例:バッシュ)。

ここでは、Bourneに似たシェルの最も一般的な演算子のみを扱います。一部のシェルには独自の追加リダイレクト演算子があります。

Ksh、bashおよびzshにも<(…)>(…)および構造があります=(…)(後者のみzsh)。これはリダイレクトではありません。プロセスの交換

答え2

「>」に関する警告

I / Oリダイレクト(<および>

注文する入力ファイル>同じファイル

または

注文する… <文書     >同じファイル

またはほぼ同等に、

文書|注文する… >同じファイル

grep、、、およびはsed、人々がこれらの構造で使用しようとするコマンドの例です。)ユーザーは、この状況によってファイルが空になる可能性があることに驚きました。cutsortspell

他の答えでは言及されていない微妙な違いは、最初の文で見つけることができますリダイレクト部分大きな打撃(1):

コマンドが実行される前に、コマンドの入力と出力が変更されることがあります。リダイレクト シェルで解釈される特殊記号を使用します。

最初の5つの単語は、太字、イタリック体、アンダースコア、ズームイン、点滅、赤色でなければならず、アイコンでマークされ、シェルがリクエスト赤い三角形に感嘆符を表示リダイレクトを実行することを強調する必要があります。 コマンド実行前。また覚えておいてください

出力リダイレクトのためにファイルが書き込み用に開かれます。

  1. したがって、この例では次のようになります。

    sort roster > roster
    

    シェルは書き込み用にファイルを開き、rosterプログラムの実行が開始される前にファイルを切り取ります(つまり、すべての内容を削除します)。sortもちろん、データを回復するために何もできません。

  2. 素朴に期待できる

    tr "[:upper:]" "[:lower:]" < poem > poem
    

    より良いかもしれません。シェルは左から右方向のリダイレクトを処理するため、書き込み(標準​​出力)のために開く前にpoem読み取り(tr標準入力)のために開きます。しかし、これは役に立ちません。この一連の操作では、2つのファイルハンドルが作成されますが、両方とも同じファイルを指します。シェルが読み取り用にファイルを開くと、内容はそのまま残りますが、プログラムが実行される前にまだ破損しています。 

それではどうすればいいですか?

ソリューションには以下が含まれます。

  • 実行中のプログラムに出力位置を指定する独自の内部機能があることを確認してください。これは通常-o(または)マークとして表示されます--output=。特に、

    sort -o roster roster
    

    ほぼ等しい

    sort roster > roster
    

    最初の場合を除いて、sortプログラムは出力ファイルを開きます。それまでは十分スマートです。後ろにすべての入力ファイルを読みました。

    同様に、少なくとも一部のバージョンsedでは-i(編集n位置)オプションは、出力を入力ファイルに書き換えるために使用できます(同様に、後ろにすべての入力を読みました。)ed/ ex、、emacs/picoなどviのエディタを使用すると、vim ユーザーはテキストファイルを編集し、編集したテキストを元のファイルに保存できます。ed(少なくとも)非対話型で使用できます。

    • vi関連機能があります。入力すると編集バッファの内容を書き込みます。:%!commandEntercommand、出力を読み取り、それをバッファに挿入します(元のコンテンツの置き換え)。
  • シンプルだが効果的:

    注文する入力ファイル>一時ファイル  && MV一時ファイル 入力ファイル

    これには次の欠点があります。input_fileリンクなので(おそらく)別のファイルに置き換えられます。また、新しいファイルはあなたの所有となり、デフォルトで保護されています。特に、これにより元のファイルがあっても、ファイルを世界中で読み取ることができるリスクが発生します。input_fileいいえ。

    多様性:

    • commandinput_file > temp_file && cp temp_file input_file && rm temp_file
      これはまだ(おそらく)去るtemp_file世界は読むことができます。より良い点は次のとおりです。
    • cp input_file temp_file && commandtemp_file > input_file && rm temp_file
      これにより、ファイルのリンク状態、所有者、およびモード(保護)が維持されますが、I / Oコストが2倍になる可能性があります。 (属性を保存するには、-aon-pなどのオプションを使用する必要があります。)cp
    • commandinput_file > temp_file &&
      cp --attributes-only --preserve=all input_file temp_file &&
      mv temp_file input_file
      (読みやすくするために別々の行で区切られます)これはファイルのモード(ルートの場合はファイルの所有者)を維持しますが、そのファイルをユーザーのものにし(ルートでない場合)、新しい別々のファイルにします。
  • このブログ (ファイルの「内部」編集)提案と説明

    {RM入力ファイル  &&  注文する… >入力ファイル; } <入力ファイル

    これを行うにはcommand標準入力を処理できます(ただし、ほぼすべてのフィルタが処理します)。ブログ自体ではこれを危険なパッチワークと呼び、使用をお勧めしません。これにより、あなたが所有し、基本的な権限を持つ別の新しいファイル(何もリンクされていません)が作成されます。

  • moreutilsパッケージには次のコマンドがありますsponge

    注文する入力ファイル|スポンジ同じファイル

    バラよりこの回答より多くの情報を知りたいです。

私を完全に驚かせたのは次のとおりです。 文法エラーが言う:

[これらのソリューションのほとんどは]読み取り専用ファイルシステムでは失敗します。ここで「読み取り専用」とは$HOME 〜する書くことができますが/tmp読み取り専用(基本的に)。たとえば、Ubuntuがあり、回復コンソールから起動した場合、これは一般的です。また、この文書演算子は必要<<<に応じて機能しません。/tmp読み書き 一時ファイルも書き込むからです。
(よりこの問題strace'd出力を含む)

この場合、次のことが機能します。

  • 上級ユーザーのみ: コマンドが入力と同じ量の出力データを生成することが保証されている場合(たとえばsorttr いいえ-dまたはオプション-s)試してみることができます。
    注文する入力ファイルdd =同じファイル変換=notrunc
    バラよりこの回答 そしてこの回答上記の説明と、コマンドが入力と同じ量の出力データを生成することを保証する可能性のある代替案を含む、詳細をご覧ください。以下(例:grep、またはcut)。これらの答えの利点は、空きスペースが必要ないことです(またはスペースがほとんど必要ありません)。上記の表に対する答えは、システムに入力(既存)ファイル全体と出力(新しい)ファイルの両方を収容するのに十分な空き容量が必要であることを明示的に要求します。これは他のほとんどのソリューション(例:と)です。例外:出力を書き込む前にすべての入力を読み取る必要があり、一時ファイルの大部分(すべてではありません)のデータをバッファリングできるため、多くの空き容量が必要になる場合があります。commandinput_file > temp_file && …sed -ispongesort … | dd …sort
  • 上級ユーザーのみ:
    注文する入力ファイル1<>同じファイル
    ddおそらく上記の答えと同じでしょう。この構文は、ファイル記述子で指定されたファイルを開きます。n<> filen 入出力用 、切らず - 一種の and の組み合わせと同じです。注:一部のプログラム(例:および)は、入力と出力が同じファイルであることを検出できるため、この場合は実行を拒否することがあります。バラよりn<n>catgrepこの回答 上記の議論とコマンドが入力と同じ量の出力データを生成することが保証されている場合、この回答が機能するようにするスクリプト以下
    警告:Peterのスクリプトをテストしていないため保証できません。

それでは、問題は何ですか?

これはU&Lの人気トピックで、次の質問で解決されます。

...スーパーユーザーやAsk Ubuntuは含まれません。上記の質問に対する回答の多くの情報をこの回答に含めましたが、すべてではありません。 (つまり、詳細については上記の質問と回答を読んでください。)

PS:私いいえ上記のブログにリンクされています。

答え3

;&, ,(と の追加観測)

  • terdonの回答の一部のコマンドは空白になることがあります。たとえば、次のように言うことができます。

    command1 ;
    

    (いいえcommand2)。これは次のとおりです。

    command1
    

    (つまり、command1前景で実行され、完了するのを待ちます。対照的に、

    command1 &
    

    (None) はcommand2バックグラウンドで起動し、すぐに別のシェルプロンプトを発行します。command1

  • 一方、、、、はcommand1 &&意味がありません。これらのいずれかを入力すると、シェルはコマンドが別の行に続くと想定します。通常、に設定されているセカンダリ(続き)シェルプロンプトが表示され、読み続けます。シェルスクリプトでは、次の行を読み、読み取った内容に追加します。 (注:これはあなたが望むものではないかもしれません。)command1 ||command1 |>

    注:一部のシェルの一部のバージョンでは、これらの不完全なコマンドをエラーとして扱うことがあります。この場合(または実際にどの\コマンドが非常に長い場合は、行の末尾にバックスラッシュ()を追加して、シェルに別の行からコマンドを読み続けるように指示できます。

    command1  &&  \
    command2
    

    または

    find starting-directory -mindepth 3 -maxdepth 5 -iname "*.some_extension" -type f \
                            -newer some_existing_file -user fred -readable -print
    
  • terdonが言ったように、(コマンド)をグループ化するために使用できます。この議論と「関連性が少ない」という主張は議論の余地があります。 terdonの答えに出てくるコマンドのいくつかはコマンドかもしれません。グループ。例えば、

    ( command1 ; command2 )  &&  ( command3; command4 )
    

    これを行う:

    • 実行しcommand1て完了するまで待ちます。
    • 次に、最初のコマンド実行結果が何でも実行され、command2完了するまで待ちます。
    • だからcommand2成功すれば、

      • 実行しcommand3て完了するまで待ちます。
      • その後、結果に関係なくコマンドを実行し、command4完了するまで待ちます。

      失敗した場合は、command2コマンドラインの処理を停止します。

  • 括弧の外では、|組み合わせは非常にタイトです。

    command1 | command2 || command3
    

    等しい

    ( command1 | command2 )  ||  command3
    

    そして&&より||密接に結ばれて;いるので

    command1 && command2 ; command3
    

    等しい

    ( command1 && command2 ) ;  command3
    

    つまり、およびcommand3/または終了状態に関係なく実行されます。command1command2

関連情報