シェルの入出力制御あれこれ

シェルスクリプトはあまり触らないから忘れちゃうのでメモっとく。

主にパイプとかリダイレクトとかプロセス置換とか。


パイプ


コマンドの出力を別のコマンドの入力にする

command1 | command2 | command3


先頭n行を表示する

command | head -10


末尾n行を表示する

command | tail -10


コマンドの出力を標準出力とファイルに出力する

command | tee file


リダイレクト


ファイルの内容をコマンドの標準入力へ渡す

command < file


コマンドの出力をファイルへ出力する

command > file


コマンドの出力をファイルに追加する

command >> file


標準エラー出力をファイルに出力する

command 2> file

2>の間にスペースを入れてはいけない。


標準エラー出力を標準出力に出力する

command 2>&1


標準出力と標準エラー出力を別々のファイルに出力する

command 1> file1 2> file2


標準出力と標準エラー出力を同じファイルに出力する

command > file 2>&1

command &> file

1> file 2> file2>&1 1> fileではダメ


出力を闇に葬り去る

command &> /dev/null


ヒアドキュメント


コマンドに複数行の入力を渡す

command <<EOS

line1
line2
EOS


タブでインデントした複数行の入力を渡す

<<-を使うと行頭のタブを取り除いた文字列が渡される。

command <<-EOS

line1
line2
EOS


出力

line1

line2


複数行の入力をファイルに出力する

cat コマンドに複数行の入力を渡し、リダイレクトでファイルへ出力する。

cat <<EOS > sample.txt

line1
line2
EOS


出力

$ cat sample.txt

line1
line2


シェル変数


コマンドの結果を変数へ格納する

コマンドをバッククォートで囲む。

bashならばコマンドを$( )で囲む記法も使える。入れ子もOK。

VAR1=`command`

VAR2=$(command $(command2))


ファイルの内容を変数へ格納する

ファイル名を$(cat )で囲む。

bashならばファイル名を$(< )で囲む記法も使える。

VAR1=$(cat file)

VAR2=$(<file)

※詳細は man bash で Command Substitution (コマンド置換) の解説を読むこと。


変数の値をファイルとしてコマンドへ渡す

ヒアストリング<<<を使用する。

command <<< $VAR1


複数コマンドの出力をまとめて制御する

{}で囲むと複数のコマンドの出力をまとめて制御できる。

#!/bin/bash

{
command1
command2
} 1> file1 2> file2

execでも同じことができる。

#!/bin/bash

exec 1> file1
exec 2> file2
command1
command2

シェルスクリプトが '> $logfile 2>&1' だらけにならなくて済んだ話 - 続・ラフなラボ


プロセス置換

<(list)>(list)をプロセス置換という。これを使うとコマンドの結果をファイルとして扱ったりできる。

bashのプロセス置換機能を活用して、シェル作業やスクリプト書きを効率化する - 双六工場日誌

Bash のプロセス置換が便利な件 - 理系学生日記


command1とcommand2の結果をcommand3にファイルとして渡す

command3 <(command1) <(command2)

上は以下のように書いたのと同じ動作。

command1 > file1

command2 > file2
command3 file1 file2


command1の結果をcommand2とcommand3に渡す

command1 | tee >(command2) | command3


command1の標準出力をcommand2に、標準エラー出力をcommand3に渡す

command1 1> >(command2) 2> >(command3)


ログ出力の実践例


標準出力、標準エラー出力をファイルにも出力する

command 1> >(tee file1) 2> >(tee file2 >&2) 


file1に全ログ、file2にフィルタリングしたログを出力する

command 2>&1 | tee file1 | grep -i error > file2


file1に全ログ、file2と標準出力にフィルタリングしたログを出力する

command 2>&1 | tee file1 | grep -i error | tee file2


file1と標準出力に全ログ、file2にフィルタリングしたログを出力する

command 2>&1 | tee >(grep -i error > file2) | tee file1


標準エラー出力の行頭に[ERROR]を付けて標準出力に出力する

command 2> >(awk '{print "[ERROR]", $0}')

  • リダイレクト
  • ヒアドキュメント
  • シェル変数
  • 複数コマンドの出力をまとめて制御する
  • プロセス置換
  • ログ出力の実践例