標準入力のリダイレクト
シェルスクリプトにおいて "リダイレクト"と聞くと、コマンドの結果をファイルに出力する(標準出力)がイメージされますが、その逆にコマンドの標準入力にリダイレクト(ファイルを入力)しているケースがあります。
command < file
(追記)tr コマンド
標準入力のリダイレクトを使ったサンプルです。
tr a-z A-Z は、標準入力から入力したアルファベットの小文字を大文字に変換するコマンドとオプションです。
text.txt から hello という文字列をリダイレクトによって trコマンドへ渡しています。
$ cat test.txt
hello
$ tr a-z A-Z < test.txt
HELLO
cat コマンド
標準入力のリダイレクトは普段から意識せずに行われていることかもしれません。
例えば、cat コマンドを見てみます。
# 標準出力をテキストファイル(text.txt)にリダイレクトする
$ echo "hello" > test.txt
# cat コマンドで内容を参照する
$ cat test.txt # hello
cat コマンドは引数に指定したファイルの内容を標準出力に表示できるコマンドですが、ここで標準入力のリダイレクトが行われているようです。
"<" が省略はされていますが、標準入力(0) に対してファイルの内容が入力され、それがコマンドに渡されているような形になります。
(追記)「多くのケースで結果は同じに見えるとは言え、仕組みは違います。」とコメントをいただきました!
"<" を省略せずに書いても、同じ結果が得られます。
"<" を付けて実行しても、同じ結果が得られることはある。
$ cat test.txt # hello
$ cat < test.txt # hello
$ cat 0< test.txt # hello
wc コマンド
wc コマンドでも同様です。
$ wc -l 0< test.txt # 1
ls コマンド
ls コマンドで標準入力(0)にルート "/" を渡してあげることで、ルートディレクトリの内容が表示されるのかもと思いましたが、カレントディレクトリの内容が表示されます。
$ ls 0< /
# カレントディレクトリの内容が表示される
ただ、更にもう一つ引数 "/" を与えることで、ルートディレクトリの内容が表示されました。
標準入力(0)に渡した入力は ls コマンドで出力する対象とは考慮されないようです。
$ ls 0< / /
# ルートディレクトリの内容が表示される
while コマンド
ファイルの内容を標準入力へリダイレクトする手法は while コマンドでは明示的に行われていることが多いと思われます。
cat test2.txt
# line1
# line2
# line3
while read line
do
echo "$line"
done < test2.txt
# line1
# line2
# line3
リダイレクト "<" が明示されており、省略はできない。
もしシェルスクリプト内で exec コマンドを使用して、カレントシェルの標準入力に予めリダイレクトしていた場合、while コマンドの標準入力に対して、改めてリダイレクトする必要はない。
# /bin/bash
exec < test2.txt
while read line
do
echo $line
done
exit 0