$()(コマンド置換)
| 対応: | 全Linux | |
|---|---|---|
| macOS(2001 Cheetah) | ||
| Bash 1.0(1989) |
コマンド置換(『$()』)はコマンドの実行結果を文字列として別の場所に埋め込みます。変数への代入・別コマンドの引数・echo での出力など幅広い場面で使えます。
構文
コマンド置換(現代的な記法)。
$(コマンド)
バッククォート(古い記法。POSIX sh でも動作します)。
`コマンド`
変数への代入。
変数=$(コマンド)
コマンドの引数として使います。
コマンド1 $(コマンド2)
ネストします($() はネストが容易です)。
$(コマンド1 $(コマンド2))
使用パターン一覧
| パターン | 概要 |
|---|---|
| var=$(cmd) | コマンドの標準出力を変数に代入します。末尾の改行は自動削除されます。 |
| echo "今日: $(date)" | 文字列の中にコマンド結果を埋め込みます。 |
| for f in $(ls *.txt) | コマンドの出力をリストとして for ループで処理します。 |
| $(cmd1 $(cmd2)) | ネストしたコマンド置換です(バッククォートではネストが難しい)。 |
| files=$(find . -name "*.php") | 複数行の出力も1つの変数に格納できます。 |
サンプルコード
コマンドの実行結果を変数に代入します。
sample_date_var.sh
today=$(date +%Y-%m-%d) echo "今日の日付: $today"
実行するコマンドは次の通りです。
bash date_var.sh 今日の日付: 2026-03-06
sample_whoami_var.sh
current_user=$(whoami) echo "実行ユーザー: $current_user"
実行するコマンドは次の通りです。
bash whoami_var.sh 実行ユーザー: okabe
ファイル数のカウントなど、コマンドの結果をそのまま使えます。
sample_count_php.sh
php_count=$(find . -name "*.php" | wc -l) echo ".php ファイル数: $php_count"
実行するコマンドは次の通りです。
bash count_php.sh .php ファイル数: 42
文字列の中にコマンド結果を埋め込みます。
echo "ホスト名: $(hostname), ユーザー: $(whoami)" ホスト名: myserver, ユーザー: okabe
コマンドの出力をファイル名に使います。
sample_logname.sh
log_file="app_$(date +%Y%m%d_%H%M%S).log" echo "ログファイル: $log_file"
実行するコマンドは次の通りです。
bash logname.sh ログファイル: app_20260306_143022.log
ネストしたコマンド置換です。『$()』はバッククォートと違いネストが容易です。
sample_nested.sh
largest=$(basename $(ls -S | head -1)) echo "最大ファイル: $largest"
実行するコマンドは次の通りです。
bash nested.sh 最大ファイル: index.php
for ループと組み合わせてファイルを一覧処理します。
sample_list_php.sh
echo "--- PHP ファイル一覧 ---"
for f in $(find . -maxdepth 1 -name "*.php" | sort); do
size=$(wc -c < "$f")
echo "$f: ${size}バイト"
done
実行するコマンドは次の通りです。
bash list_php.sh --- PHP ファイル一覧 --- ./ajax.php: 8340バイト ./index.php: 5120バイト
なお、for 文はターミナルでも直接入力できます。『do』の後で Enter を押すと『> 』マークが表示され、これは「まだ入力が続く」というサインで、『done』を入力すると実行されます。
for f in $(find . -maxdepth 1 -name "*.php" | sort); do
size=$(wc -c < "$f")
echo "$f: ${size}バイト"
done
./ajax.php: 8340バイト
./index.php: 5120バイト
複数行の出力を変数に格納して処理します。
sample_count_dirs.sh
dirs=$(find . -maxdepth 1 -type d) echo "ディレクトリ数: $(echo "$dirs" | wc -l)"
実行するコマンドは次の通りです。
bash count_dirs.sh ディレクトリ数: 8
概要
コマンド置換の結果は末尾の改行が自動的に削除されます。複数行の出力を変数に格納する場合は行が保持されますが、ダブルクォートなし(『$変数』)で展開すると改行がスペースに変換されます。複数行を1行ずつ処理するには『"$変数"』でクォートして while read ループに渡します。
バッククォート(『`cmd`』)はネストが難しく視認性も低いため、多くの場面で『$()』が使われています。
コマンドの出力を別コマンドに引数として渡すには xargs も有用です。
よくあるミス
よくあるミス1: クォートなしで展開すると単語分割される
コマンド置換の結果をクォートなしで展開すると、スペースや改行で分割されてしまいます。
files=$(find . -name "*.txt")
for f in $files; do
echo "$f"
done
修正後は次の通りです。
bash list.sh (スペースを含むファイル名が分割されて表示される)
ファイル名にスペースが含まれる可能性がある場合はクォートするか、while read のパターンを使います。
while IFS= read -r f; do
echo "$f"
done < <(find . -name "*.txt")
よくあるミス2: 末尾の改行が消えることを忘れる
コマンド置換は末尾の改行を自動で取り除きます。改行を含む出力を変数に格納すると最後の行の改行が消えます。
result=$(printf "a\nb\nc\n") echo "$result" a b c
末尾の改行は削除されていますが、中間の改行は保持されています。末尾改行を保持したい場合は変数展開後に改行を付け足す工夫が必要です。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。