read コマンド入門 - シェルスクリプトで入力を受け取る
「スクリプトの途中で、ユーザーに名前やパスワードを入力してもらいたい」——そんなときに使うのが read コマンドです。この記事では、ライニー先輩とリナの会話を通じて、read でキーボード入力やファイルを受け取る方法を一緒に学んでいきましょう。
この記事でわかること
readコマンドが何をするコマンドなのかがわかる- プロンプト表示(
-p)・パスワード非表示(-s)・タイムアウト(-t)の使い方を習得できる while readでファイルを1行ずつ処理する定番パターンが書ける- 初心者がハマりやすい「パイプの落とし穴」「
-rを付ける理由」を理解できる
1. read コマンドって何?
結論: read は標準入力から1行を読み取って変数に入れる組み込みコマンドで、スクリプトをユーザーと対話させるための入り口になる。
read コマンドの出番だよ。read はキーボードから打たれた1行を読み取って、変数に入れてくれるコマンドなんだ。read コマンドとは
read は、標準入力(キーボードなど)から1行を読み取り、変数に格納するシェルの組み込みコマンドです。ユーザーに何かを入力してもらい、その内容をスクリプトの中で使いたいときに利用します。
ls とか cat とは違うんですか?ls や cat は /bin/ls のように実行ファイルが存在するコマンドなんだけど、read はシェル自身が持っている機能なんだ。だから which read で探しても出てこないことが多いよ。type read で確認してみると read is a shell builtin って表示されるんだ。2. いちばん基本の使い方
結論: read 変数名 と書くと入力待ちになり、Enter を押すまでの1行がその変数に入る。
read name
リナ って入力して Enter を押すと...?name という変数に入るんだ。中身を確認してみよう。read name リナ echo "こんにちは、$name さん"
こんにちは、リナ さん
変数の中身を見るには $ を付ける
read name で入れた値は、$name のように頭に $ を付けて取り出します。echo "$name" のようにダブルクォートで囲むのが安全な書き方です(値に空白が含まれても正しく扱えます)。
3. プロンプトを表示する(-p)
結論: read -p "メッセージ" 変数名 と書くと、入力欄の前に案内文を表示できる。
-p オプションで**入力を促すメッセージ(プロンプト)**を一緒に表示するんだ。read -p "お名前を入力してください: " name echo "ようこそ、$name さん"
お名前を入力してください: リナ ようこそ、リナ さん
-p の後ろに書いた文字列がそのまま表示されるよ。: のように最後に空白を入れておくと、入力位置が見やすくなるからおすすめだよ。4. 複数の値を一度に受け取る
結論: read に変数名を複数並べると、空白で区切られた入力をそれぞれの変数に振り分けられる。
read の後ろに変数名を空白で区切って並べるんだ。入力も空白で区切ると、それぞれに振り分けられるよ。read -p "姓 名 を入力: " sei mei echo "姓: $sei / 名: $mei"
姓 名 を入力: 山田 リナ 姓: 山田 / 名: リナ
変数より入力が多いと、最後の変数にまとめて入る
read a b のように変数が2つなのに 1 2 3 4 と入力すると、a には 1、b には残り全部(2 3 4)が入ります。逆に入力が少ないと、余った変数は空のままになります。
5. パスワードを隠して入力する(-s)
結論: read -s は入力した文字を画面に表示しないので、パスワードなど見られたくない入力に使う。
-s(silent)オプションだよ。入力した文字が画面に表示されなくなるんだ。パスワードや秘密の値を受け取るときに使うよ。read -s -p "パスワード: " pass
echo
echo "入力された文字数: ${#pass}"パスワード: 入力された文字数: 8
-s は文字を表示しないだけで、中身はちゃんと変数に入っているんだ。-s を使うと Enter を押しても改行が表示されないから、直後に echo で改行を1つ入れておくと見た目がきれいになるよ。${#pass} は変数の文字数を表す書き方だよ。6. 入力を時間制限つきにする(-t)
結論: read -t 秒数 を使うと、指定した秒数以内に入力がないと read が自動で終了する。
-t(timeout)だよ。指定した秒数だけ待って、入力がなければ次に進むんだ。if read -t 5 -p "5秒以内に入力してね: " answer; then
echo "入力されました: $answer"
else
echo
echo "時間切れです"
firead の成功・失敗を if で判定できる
read は、正常に1行読めれば「成功」、タイムアウトや入力の終わり(後述)になると「失敗」を返します。これを if read ...; then の形で受け取ると、入力があったかどうかで処理を分けられます。
7. ファイルを1行ずつ読む(while read)
結論: while read line; do ... done < ファイル で、ファイルを1行ずつ変数に取り込んで処理できる。
while read の組み合わせがいちばんだよ。これはシェルスクリプトの超定番パターンだから、形ごと覚えておくと一生使えるよ。while read line; do
echo "読んだ行: $line"
done < list.txt< list.txt の部分は何ですか?list.txt の中身を read に流し込んでね」という意味だよ。read は1行読むたびに line に入れて、行がなくなるまでループを繰り返すんだ。ファイルの最後まで読むと read が「失敗」を返すから、自然にループが終わるんだよ。より安全な型: while IFS= read -r line
実務では while IFS= read -r line; do ... done < file という形をよく見ます。IFS= は行頭・行末の空白が削られるのを防ぎ、-r はバックスラッシュ(\)をそのまま読み込むための指定です。理由は次の章で説明します。
8. 初心者がハマる2つの落とし穴
結論: パイプで渡した while read は別プロセスで動くため変数が消える点と、-r なしだとバックスラッシュが消える点に注意する。
while read を使ったら、ループの中で数えた数がループの後で 0 に戻ってて...バグですか?落とし穴1: パイプの中の変数は外に残らない
count=0
cat list.txt | while read line; do
count=$((count + 1))
done
echo "$count" # ← 0 になってしまうcat ... | while ... のようにパイプでつなぐと、while の部分が**別のプロセス(サブシェル)**で動くんだ。その中で count を増やしても、それは「分身」の中だけの話。元の count には反映されないんだよ。解決策: パイプではなくリダイレクトを使う
count=0
while read line; do
count=$((count + 1))
done < list.txt
echo "$count" # ← 正しく数えられる< list.txt のリダイレクトなら、while は同じプロセスの中で動くので、count の変更がちゃんと残ります。
落とし穴2: -r を付けないとバックスラッシュが消える
-r って、なんで付けるんですか?-r を付けないと、read はバックスラッシュ(\)を特別扱いして消してしまうんだ。例えばファイルのパス C:\Users を読むと C:Users になっちゃう。だから「入力された文字をそのまま読みたい」ときは -r を付けるのが鉄則だよ。# -r なし: \ が消えてしまう echo 'C:\Users\rina' | read path; echo "$path" # → C:Usersrina # -r あり: そのまま読める echo 'C:\Users\rina' | read -r path; echo "$path" # → C:\Users\rina
迷ったら -r を付ける
特別な理由がない限り、read には -r を付けるのが安全です。シェルスクリプトのチェックツール(ShellCheck など)も、-r なしの read を警告します。
9. ミニ課題で復習しよう
課題: あいさつスクリプトを書いてみよう(クリックで解答例)
お題: 「お名前は?」と尋ね、入力された名前を使って「こんにちは、〇〇さん!」と表示するスクリプトを書いてください。
解答例:
#!/bin/bash
read -p "お名前は? " name
echo "こんにちは、${name}さん!"-p でプロンプトを出し、$name で受け取った値を表示しています。${name} のように {} で囲むと、変数名の区切りがはっきりして安全です。
read -p でプロンプトを出して、$name で表示するんですね。read は短いコマンドだけど、-p・-s・-t・while read の4つを押さえれば、たいていの「入力を受け取る場面」に対応できる。あとは実際のスクリプトでどんどん使って慣れていこう。