コマンド置換 (command substitution) 入門 — $(...) でコマンド結果を変数に取り込む
この記事でできるようになること
- `$(コマンド)` でコマンドの実行結果を文章に埋め込める
- `VAR=$(コマンド)` で実行結果を変数に保存できる
- `"$(...)"` と囲む理由を説明できる。バッククォートとの違いもわかる
前提知識(先に読むと理解しやすい記事)
この記事で学べること
- コマンド置換 という考え方がわかります
$(コマンド)で 実行結果を変数に取り込む 方法がわかります- 古い書き方である バッククォート
`...`との違いがわかります - なぜ
"$(...)"と クォート文字列を引用符(' や ")で囲むこと。スペースなどを含む値をひとまとまりとして扱える。で囲む のかがわかります
言葉の整理
- 変数:値を入れておく名前付きの箱です。名前を書けば、中身を取り出せます。
- コマンド置換:コマンドの実行結果を、その場の文字として埋め込む仕組みです。「コマンド展開」「Capturing Output」と呼ばれることもあります。
- クォート:引用符のことです。
"..."をダブルクォート、'...'をシングルクォートと呼びます。
なお、この記事で使う date / pwd / whoami / ls は、すべて表示だけを行うコマンドです。ファイルを消したり書きかえたりはしません。何度打ち間違えても、あなたのパソコンは壊れません。
結論(先に覚えるべき型)
- コマンドの結果を 変数に入れる →
VAR=$(コマンド) - 結果を 文章に埋め込む →
echo "今日は $(date)" - 迷ったら
"$(...)"とダブルクォートで囲む
1. コマンド置換とは何か?
結論: コマンド置換はコマンドの実行結果を、その場の文字列として埋め込む仕組み。
$(...)で書く。
date を実行すると今日の日付が出ますよね。あの結果を別のコマンドの中で使いたいです。どうすればいいでしょうか。$(コマンド) と書くと、その部分が コマンドの実行結果に置き換わる んだ。$(date) と書くと、シェル入力したコマンドを解釈してコンピュータに実行させる対話プログラム。はまず date を実行する。その出力で $(date) を丸ごと差し替える。そのうえでコマンド全体を実行するんだ。$ echo "今日は $(date) です"
今日は 2026年 6月 5日 金曜日 12:00:00 JST です
置き換えのイメージ
echo "今日は $(date) です"
↓ date を先に実行
echo "今日は 2026年 6月 5日 ... です"$(...) の中身が 実行結果という名の文字列 に化けてから、外側のコマンドが動く。
2. 結果を変数に取り込む
結論:
VAR=$(コマンド)でコマンドの出力を変数に保存できる。=の前後にスペースを入れないのが鉄則。
2-1. 基本形
$ today=$(date +%Y-%m-%d) $ echo "$today"
2026-06-05
today という変数に日付が入りましたね! これは便利。$ logfile="backup-$today.log" $ echo "$logfile"
backup-2026-06-05.log
2-2. = の前後にスペースを入れない
変数の代入では、= の前後にスペースを入れてはいけません。
today = $(date) # NG: today というコマンドを探しに行ってエラー today=$(date) # OK
スペースを入れると、シェルは today を コマンド名 だと解釈します。そのため command not found になります。
3. バッククォートとの違い
結論: 古い書き方の
`...`でも同じ動作。しかし入れ子や可読性で不利なため、今は$(...)を使う。
`date` のようにバッククォートで囲んでいる記事もありました。あれは何でしょうか。$(date) とほぼ同じ。ただ今は $(...) を使うのが推奨なんだ。# 古い書き方(バッククォート) $ echo "今日は `date` です" # 新しい書き方(推奨) $ echo "今日は $(date) です"
$(...) が推奨される理由
| 観点 | バッククォート `...` |
$(...) |
|---|---|---|
| 入れ子 | 書きにくい(要エスケープ) | そのまま書ける |
| 見やすさ | 縦棒と紛らわしい | 括弧で明確 |
| 引用符の扱い | クセがある | 素直 |
バッククォートは、古い記事を読むときに理解できれば十分です。自分で書くときは $(...) に統一しましょう。
4. 入れ子(ネスト)で組み合わせる
結論:
$(...)は中にさらに$(...)を書ける。内側から順に実行され、結果が外側へ渡る。
$ echo "$(basename $(pwd))"
myproject
$(...) の中に、また $(...) がありますね。これはどう動くのでしょうか。basename が受け取って、末尾の myproject だけを取り出すんだ。basename はパスから最後の名前だけを取り出すコマンドだよ。内側から外側への流れ
basename $(pwd)
↓ pwd を実行
basename /home/user/myproject
↓ basename を実行
myprojectバッククォートの場合、内側を \` と書き直す必要があります。この書き直しをエスケープと呼びます。手間がかかります。
$(...) なら そのまま入れ子にできます。これが大きな強みです。
5. クォートで囲む理由
結論:
"$(...)"とダブルクォートで囲むと、結果に空白や改行があっても 1 つの値として安全に扱える。
5-1. リナの失敗:クォートを忘れて改行が消える
$ files=$(ls) $ echo $files # クォートなし
Documents Downloads report.txt
$(...) の結果はスペースや改行の位置でバラバラの単語に分けられる。これを単語分割と呼ぶよ。echo はその単語をスペース区切りで並べ直す。だから横一列に見えるんだ。$ echo "$files" # クォートあり
Documents Downloads report.txt
5-2. 迷ったら囲む
コマンド置換の結果は、基本的に "$(...)" とダブルクォートで囲みます。
- ファイル名にスペースが含まれていても壊れません
- 改行がそのまま保たれます
- 結果が空のときに、引数ごと消えてエラーになるのを防げます
「迷ったら囲む」を習慣にするだけで、事故の大半を防げます。
6. よくある初心者のつまずき
結論: 末尾の改行は自動で消える、
$()の中でも変数は使える、の 2 点を押さえると混乱しにくい。
6-1. 末尾の改行は取り除かれる
$ count=$(ls | wc -l) $ echo "ファイル数は $count 個"
ファイル数は 3 個
コマンド置換は、出力の末尾にある改行を自動で取り除きます。 だから上の例のように、数値をそのまま文章へ埋め込めます。
6-2. $() の中でも変数や引数が使える
$ dir=/etc $ echo "$dir のファイル数: $(ls "$dir" | wc -l)"
/etc のファイル数: 220
$(...) の中は ふつうのコマンドラインと同じ です。変数も、パイプも、別のコマンド置換も自由に書けます。
6-3. 結果が空でも壊れないようにする
$ result="$(grep "存在しない語" file.txt)" $ echo "[$result]"
[]
クォートで囲んでいれば、検索結果が空でも [] と表示されるだけで済みます。
クォートを外すと、引数そのものが消えます。そのため思わぬ動作の原因になります。
7. ミニ課題:実際にやってみよう
結論: 変数代入・文章への埋め込み・入れ子の 3 問で、コマンド置換の基本を手で確かめる。
課題 1: 現在のユーザー名を me という変数に入れて、文章の中で表示しよう。
ヒント 1(方向づけ)を見る
まずユーザー名を調べるコマンドを実行します。その結果を箱に入れ、あとから文章の一部として取り出します。
ヒント 2(コマンド名)を見る
ユーザー名は whoami でわかります。箱に入れる形は 変数名=$(コマンド) です。表示は echo です。
答えを見る
$ me=$(whoami) $ echo "私は $me です"
私は lina です
表示される名前は、お使いの環境によって変わります。
課題 2: 「現在のディレクトリファイルをまとめて整理する入れ物。Windows や macOS の「フォルダ」と同じもの。は ◯◯ です」という文章を、pwd の結果を埋め込んで表示しよう。
ヒント 1(方向づけ)を見る
今回は変数を使いません。文章の中に、コマンドの結果を直接はめ込みます。
ヒント 2(コマンド名)を見る
現在地は pwd でわかります。文章全体をダブルクォートで囲み、$(pwd) を差し込みます。
答えを見る
$ echo "現在のディレクトリは $(pwd) です"
現在のディレクトリは /home/lina/myproject です
表示されるパスは、お使いの環境によって変わります。
課題 3: 今いるディレクトリの 名前だけ を表示しよう。パス全体ではなく、末尾の 1 つだけです。
ヒント 1(方向づけ)を見る
2 段構えです。まず現在地のパス全体を取り出します。次にそのパスから、末尾の名前だけを取り出します。
ヒント 2(コマンド名)を見る
パス全体は pwd です。末尾だけを取り出すのは basename です。$(...) を入れ子にします。
答えを見る
$ echo "$(basename "$(pwd)")"
myproject
pwd が取得したパスの末尾だけを basename が取り出します。内側の $(pwd) から先に実行される点を確かめてください。
8. 振り返り
$(コマンド) は、その場所をコマンドの実行結果に置きかえる書き方ですね。VAR=$(コマンド) の形にする。"$(...)" と囲む。囲まないと単語分割で崩れてしまうんですね。$(...) に統一しよう。9. コピペ用テンプレート
結論: 代入・埋め込み・ファイル名生成・カウントのよく使う型をまとめて手元に置いておく。
よく使う型をまとめておく
# 結果を変数に入れる VAR=$(コマンド) # 文章に埋め込む(必ずダブルクォート) echo "結果は $(コマンド) です" # 日付入りのファイル名を作る logfile="app-$(date +%Y%m%d).log" # 行数を数えて変数に count=$(ls | wc -l) # 入れ子で組み合わせる name="$(basename "$(pwd)")"
今日の 3 行まとめ
$(コマンド)は、その場所をコマンドの実行結果に置きかえる- 変数に入れるときは
VAR=$(コマンド)。=の前後にスペースを入れない - 結果を使うときは
"$(...)"と囲む。囲まないと空白や改行で分割される