シェルスクリプトは非常に強力な機能を提供します。コマンドやスクリプトからの出力をリダイレクトしてファイルやデバイスに送信したり、他のコマンドやスクリプトへの入力として送信したりする機能です。
この記事では、コマンドとスクリプトの出力に焦点を当てています。
出力の種類
シェル内のコマンドとスクリプトは、2つの基本的なタイプの出力を生成できます。
- STDOUT: コマンド/スクリプト(ファイル記述子1)からの通常の出力
- STDERR: コマンド/スクリプト(ファイル記述子2)からのエラー出力
デフォルトでは、STDOUTとSTDERRが端末の画面に送信されます。
入力に関しては、 STDIN デフォルトでは、キーボードからの入力を読み取ります(ファイル記述子0)。ファイル記述子は、ファイルまたはその他のI/Oリソースの一意の識別子です。
シェル出力をリダイレクトする方法
シェルスクリプトとコマンドからの出力をリダイレクトする方法は複数あります。
1。 STDOUTをリダイレクトする
次の例では、この単純なファイルのセットを使用します。
$ls -la file*
-rw-r--r--. 1 admin2 admin2 7 Mar 27 15:34 file1.txt
-rw-r--r--. 1 admin2 admin2 10 Mar 27 15:34 file2.txt
-rw-r--r--. 1 admin2 admin2 13 Mar 27 15:34 file3.txt
単純なls
を実行しています STDOUTとSTDERRを説明するコマンドですが、同じ原則がシェルから実行するほとんどのコマンドに適用されます。
ls file* > my_stdout.txt
を使用して標準出力をファイルにリダイレクトできます :
$ls file* > my_stdout.txt
$ cat my_stdout.txt
file1.txt
file2.txt
file3.txt
次に、同様のコマンドを実行しますが、1
>
の前 。 >
を使用したリダイレクト 信号は1>
を使用するのと同じです そうするために:私はシェルにSTDOUTをそのファイルにリダイレクトするように指示しています。ファイル記述子を省略すると、デフォルトでSTDOUTが使用されます。 sdiff
を実行することでこれを証明できます 両方のコマンドの出力を並べて表示するコマンド:
$ls file* 1> my_other_stdout.txt
$sdiff my_stdout.txt my_other_stdout.txt
file1.txt file1.txt
file2.txt file2.txt
file3.txt file3.txt
ご覧のとおり、両方の出力の内容は同じです。
2。 STDERRをリダイレクトする
さて、STDERRの何が特別なのですか?実例を示すために、ls file* non-existing-file* > my_normal_output.txt
を使用して前の例にエラー条件を導入します。 :
結果は次のとおりです。
画像
上記のテストからのいくつかの観察結果は次のとおりです。
- 既存のファイルに関する出力は、宛先ファイルに正しく送信されます。
- エラー(存在しないものをリストしようとすると表示されます)が画面に送信されます。これは、リダイレクトしない限り、エラーが送信されるデフォルトの場所です。
[Bash Shell ScriptingCheatSheetをダウンロードします。 ]
次に、ファイル記述子2をls file* non-existing-file* > my_normal_output.txt 2> my_error_output.txt:
で明示的に参照して、エラー出力をリダイレクトします。

上記の例では:
-
ls
コマンドは、以前のように画面にエラーメッセージを表示しません。 - 通常の出力には、私が期待するものが含まれています。
- エラーメッセージは
my_error_output.txt
に送信されます ファイル。
3。 STDOUTとSTDERRを同じファイルに送信します
もう1つの一般的な状況は、STDOUTとSTDERRの両方を同じに送信することです。 ファイル:
$ls file* non-existing-file* > my_consolidated_output.txt 2>&1
$ cat my_consolidated_output.txt
ls: cannot access 'non-existing-file*': No such file or directory
file1.txt
file2.txt
file3.txt
この例では、すべての出力(通常とエラー)が同じファイルに送信されます。
2>&1
構築とは、「STDOUTを送信するのと同じ場所にSTDERRを送信する」という意味です。 。"
4。出力をリダイレクトしますが、ファイルを追加します
これまでのすべての例では、出力をリダイレクトするたびに、単一の>
を使用しました。 、これは「このファイルに何かを送信し、ファイルを最初から開始する」という意味です。 。"その結果、宛先ファイルが存在する場合、それは上書きされます。
追加したい場合 既存のファイルに対して、>>
を使用する必要があります 。ファイルがまだ存在しない場合は、作成されます:
$echo "Adding stuff to the end of a file" >> my_output.txt
$cat my_output.txt
file1.txt
file2.txt
file3.txt
Adding stuff to the end of a file
5。別のプロセスにリダイレクトするか、どこにもリダイレクトしない
上記の例では、出力をファイルにリダイレクトする方法について説明していますが、出力を他のプロセスまたはdev/null
にリダイレクトすることもできます。 。
他のプロセスに出力を送信することは、シェルの最も強力な機能の1つです。このタスクでは、|
を使用します (パイプ)シンボル。1つのコマンドからの出力を次のコマンドの入力に送信します:
ps -ef | grep chrome | grep -v grep | wc -l
21
上記の例は私のプロセスをリストし、文字列 chromeを含むすべてのプロセスをフィルタリングします 、私のgrep
に関する行を無視します コマンドを実行し、結果の行をカウントします。出力をファイルに送信する場合は、>
を追加します チェーンの最後にあるファイル名。
最後に、出力の1つであるSTDERRを無視したい例を次に示します。
$tar cvf my_files.tar file* more-non-existing*
file1.txt
file2.txt
file3.txt
tar: more-non-existing*: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous errors
tar
コマンドは、more-non-existing
で始まる名前のファイルを見つけられませんでした 、最後にいくつかのエラーメッセージが表示されます。
いくつかのスクリプトを作成し、これらのエラーの表示やキャプチャを気にしないとします(実際には、エラーを無視するだけでなく、防止して処理する必要があります):
$tar cvf my_files.tar file* more-non-existing* 2> /dev/null
file1.txt
file2.txt
file3.txt
/dev/null
は「ブラックホール」のような特別なデバイスファイルです。そこに送信したものは消えてしまいます。
[Linuxにアプリケーションをインストールするためのこのガイドをダウンロードしてください。 ]
6。スクリプトでリダイレクトを使用する
画像
=== SUMMARY OF INVESTIGATION OF chrome ===
Date/Time of the execution: 2022-03-25 18:05:50
Number of processes found.: 5
PIDs:
1245475
1249558
1316941
1382460
1384452
この非常に単純なスクリプトは次のことを行います:
- 3行目:オペレーティングシステムでコマンドを実行し、変数DATE_TIMEに保存します。
- 6行目:
ps
を実行します コマンドを実行し、grep
にリダイレクトします とファイルに。- 出力をファイルに送信する代わりに、(3行目のように)変数に送信することもできますが、この場合、同じ出力を使用して他のアクションを実行したいので、それをキャプチャします。より現実的な状況では、ファイルを用意しておくと、開発やトラブルシューティングの際にも役立つ可能性があるため、コマンドが生成するものをより簡単に調査できます。
- 8行目:追加のコマンドを実行し、出力を
wc
にリダイレクトします 、結果を変数に割り当てます。 - 9行目:
awk
を使用 出力から列2のみを選択し、降順で並べ替えます(別のパイプを追加するため)。
まとめ
これらは、STDOUTとSTDERRをリダイレクトするいくつかの例です。これらすべてをまとめると、リダイレクトがいかに強力であるかがわかります。個々のコマンドを連鎖させ、それらの出力を操作し、その結果を次のコマンドの入力として使用することにより、スクリプトまたはプログラムの開発が必要になる可能性のあるタスクを実行できます。すべてを構成要素として使用して、この手法を他のスクリプトに組み込むこともできます。