echo コマンド入門から実務まで|ファイル出力・標準エラー・色付け

未分類

シェルで最もよく使う基本コマンドのひとつが echo です。
変数の中身確認、パイプの前段での固定文字列出力、ワンライナーでの設定ファイル生成など、日常作業から本番スクリプトまで幅広く活躍します。

ただし、次のような“ちょっとした違い”が思わぬ不具合を招くこともあります。

  • echo -e が効いたり効かなかったりする(シェルや環境で挙動差)
  • -n の扱いがバラつく、意図せず改行が入る/消える
  • echo *グロブ展開されてファイル名の羅列に置き換わる
  • -e から始まる文字列がオプションと誤解される
  • echo がビルトインか /bin/echo かで挙動が変わる
  • Windowsの ECHO は表示だけでなく echo on/off によるコマンドエコー制御も担う

本記事では、入門者でもすぐ実務に使えるように、基礎から“事故りやすいポイント”までを一気に整理します。取り上げる主な内容は次のとおりです。

  • 改行制御:-n と「改行なし」出力の安全な書き方
  • エスケープ解釈:-e / -E と可搬性、printf への置き換え
  • リダイレクト:>(上書き)/ >>(追記)の実務注意点
  • 標準エラー出力:>&2 でのエラー表示とログ設計
  • ANSIカラー出力:\x1b[31m を使った確実な色付けのテンプレ
  • グロブ・先頭ハイフン対策:クォートと -- の使い方
  • Linux/UNIX と Windows(CMD)の違いと使い分け

ゴールはシンプルです。
「どの環境でも、意図したとおりに、迷いなく出力できる」――そのための原則とレシピを、最短ルートで身につけましょう。

  1. echoコマンドの基本
    1. 標準出力と空行(引数なしの挙動)
    2. 変数展開・コマンド置換の最短例
  2. 改行の制御とファイル出力
    1. -n と改行なし出力(失敗例と成功例)
    2. > / >> リダイレクトの実務注意
  3. 「-e」が効かない原因と対処
    1. そもそもPOSIXではオプションなし(-eは非規格)
      1. まず確認すること
    2. Bashの拡張と xpg_echo(挙動が変わるスイッチ)
    3. シェル/実装差のクイック比較
    4. 可搬性重視なら printf へ——置換レシピ集
      1. 「効かない」ときのチェックリスト
  4. エスケープシーケンス完全ガイド
    1. よく使うエスケープと実例(安全な書き方つき)
    2. 認識されない場合のチェック手順
  5. ANSIカラーの安全な出し方
    1. \e より \x1b/3 を使う(環境差を抑える)
    2. 使い回せるテンプレ(関数・変数で管理)
    3. “色を出すべきときだけ”出す(TTY判定・無効化フラグ)
    4. “色を剥がす”ユーティリティ
  6. 実務でハマる落とし穴と対策
    1. グロブ展開とクォート(echo * と echo "*")
    2. ビルトインと /bin/echo の違い(実体確認)
    3. エラーは標準エラーへ(>&2)
  7. 【Windows CMD】ECHOの基本とバッチ実務
    1. echo on/off と現在設定の確認、@echo off の意味
    2. 空行の出し方と安全策(echo. / echo()
    3. 特殊文字のエスケープ(^ と %%)
    4. 変数が空のときの「ECHO はオフです。」を避ける
    5. 改行なしで出す(set /p テクニック)
    6. ちょい便利:色付き表示(CMD)
  8. 目的別チートシート(Linux/UNIX & Windows)
    1. Linux/UNIX の定番レシピ(コピペOK)
    2. Windows CMD の定番レシピ(コピペOK)
  9. よくある質問(FAQ)
    1. Q1. echo -e が効いたり効かなかったりします。どうすれば?
    2. Q2. 改行なしで安全に出すには?
    3. Q3. 先頭が - の文字列がオプションと誤認されます。
    4. Q4. echo * がファイル名に展開されてしまいます。
    5. Q5. 色付けは \e と 3 のどちらが良い?
    6. Q6. ログで通常出力とエラーを分けたい。
    7. Q7. CI など環境で色を無効化したい。
    8. Q8. /bin/echo とビルトイン echo の違いで事故ります。
  10. 参考・参照リンク
  11. 関連記事

echoコマンドの基本

標準出力と空行(引数なしの挙動)

echo は、与えた引数を空白で連結して末尾に改行を付けて標準出力へ書き出します。引数がなければ**空行(改行のみ)**を出力します。最小限のルールは次のとおりです。

  • 引数はスペース区切りで並べた順に出力される
  • 末尾には原則として改行が付く(改行を抑止する方法は後述)
  • 引数なしの echo空行を出す
echo Hello World      # => Hello World\n
echo                  # => \n(空行)
echo "Hello   World"  # => Hello   World\n(連続スペースを保持)

スペースやワイルドカード(* など)を意図どおりに出すには、クォートが必須です。クォートがないとシェルが単語分割グロブ展開を行い、出力が変わります。

echo *          # => カレントのファイル名一覧に展開される
echo "*"        # => *(アスタリスクそのものを出力)
echo "$PATH"    # => 変数PATHの中身を出力(空白や:を保持)

よくある勘違いとして、echo ""echo の違いがあります。どちらも改行1つを出す点では同じですが、前者は空文字を1引数として渡すという違いがあり、スクリプトで「引数の個数」を検査するような場面では区別が意味を持つことがあります。

ポイント

見せたい文字はクォートする(空白・記号・日本語を壊さない)
見せたくない展開は止める"*" のようにクォート)
空行は echo 単体でOK(printf を使う場合は printf '\n'

変数展開・コマンド置換の最短例

echo確認とログに最適です。変数やコマンド結果をすばやく可視化できます。

name="Alice"
echo "Hello, $name"          # => Hello, Alice

echo "Today is $(date +%F)"  # => Today is 2025-08-31 など

files=$(ls | wc -l)
echo "files: $files"         # => files: 42 など

ダブルクォート(")は変数やコマンド置換を展開しつつ、空白や改行を1引数として保持するのに便利です。対してシングルクォート(')は中身を一切展開しないため、リテラルとしてそのまま出したい文字列に使います。

echo "cost: ${price}円"   # 変数展開あり
echo 'cost: ${price}円'   # そのまま出力(変数展開しない)

また、先頭がハイフンの文字列を安全に出したい場合、echoオプションと誤解することがあるため注意が必要です。実務では次のどちらかを使います。

  • 文字列を先に配置して -- でオプション終端を明示(シェルによっては効かないことがある)
  • printf を使う(確実で移植性が高い。詳細は後述)
str="-n looks like option"
echo -- "$str"        # 環境によっては安全
# より安全:printf
printf '%s\n' -- "$str"

この基本さえ押さえれば、echo は「値をすぐ見る」「ログに一言残す」「パイプの前段で定型文字列を渡す」といった用途で迷いなく使える土台になります。

改行の制御とファイル出力

-n と改行なし出力(失敗例と成功例)

echo は標準で末尾に改行を付けます。ログや人間向けの出力では便利ですが、改行が意味を持つプロトコルやパイプ処理では邪魔になることがあります。よく使われるのが -n(改行抑止)ですが、環境によってはオプションとして認識されないことがある点に注意が必要です。

  • 典型例 echo -n "TOKEN="; cat token.txt # 期待: TOKEN=<ファイル内容> と同一行に並ぶ ある実装では -n がそのまま文字として出力され、-n TOKEN=... になってしまいます。
  • 安全な書き方(移植性重視) # 改行なしは printf が確実 printf '%s' "TOKEN=" cat token.txt printf必ず指定どおりのフォーマットで出力するため、-n の解釈差で崩れません。
  • 先頭がハイフンの文字列対策 s="-n is not option" # echo は解釈ミスの恐れ。-- を付けても実装により不安 # echo -- "$s" printf '%s\n' -- "$s" # ← 最も安全
  • コマンド置換内の改行 ver=$(printf '%s' "$(app --version)") # とにかく改行を入れたくない echo は暗黙の改行が混入しやすく、変数に余計な改行が入る事故が起きがちです。printf を使えば制御が明確です。
  • 可読性のコツ
    • 人間向け出力 → echo(改行あり)
    • 機械向け出力 → printf(改行の有無を明示)

短いスクリプトでも「改行が1つ入るか入らないか」で挙動が変わる処理は少なくありません。-n を使う場面では常に「実行シェルと実装差」を意識し、確実性が要るときは printf を選びます。

> / >> リダイレクトの実務注意

ファイルへ出力する最短手段はリダイレクトです。>上書き>>追記。その上で、実務では次のポイントを押さえると事故が減ります。

  • 上書き事故の回避 set -o noclobber # 既存ファイルへの > 上書きを禁止 echo "config" > file # 既存なら失敗(安全側) echo "force" >| file # 明示的に許可する場合のみ >| を使う
  • 空ファイルだけ作る(ログのローテートなど) : > app.log # 内容を消して空にする(安全で高速)
  • 複数行の安全な書き込み cat > /etc/myapp.conf <<'EOF' key=value path=/opt/myapp EOF 変数展開を抑止したい場合はヒアドキュメントの区切り語をクォートします。
  • 画面にも出しつつ保存 echo "deploy started" | tee -a deploy.log tee -a追記しながら可視化できます。権限が必要なパスへは sudo tee を使うと安全です。 echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
  • パスは必ずクォート out="/var/log/my app/output.log" printf '%s\n' "ok" >> "$out" # スペース・ワイルドカード対策
  • 一時ファイル→原子的な差し替え tmp=$(mktemp) printf '%s\n' "new config" > "$tmp" install -m 0644 "$tmp" /etc/myapp.conf # 権限も同時に指定 rm -f "$tmp" 直接書き換えるより中間ファイルからの置換の方が壊れにくく、読み手(他プロセス)にも優しいです。
  • 標準エラーに出したい(ファイル出力と混ぜない) printf '%s\n' "ERROR: failed" >&2 ログ設計では**stdout(通常メッセージ)stderr(エラー)**を分けると集計・監視が容易になります。
  • 権限とumaskを意識
    生成ファイルの権限は umask の影響を受けます。重要な設定ファイルは install -m 0640 のように明示すると安全です。

リダイレクトは一見単純ですが、上書きの不可逆性権限・展開・原子性など、運用で効く“地味な事故対策”が成果を分けます。上のパターンをテンプレとして覚えておくと、どのプロジェクトでも同じ品質で扱えます。

「-e」が効かない原因と対処

そもそもPOSIXではオプションなし(-eは非規格)

多くの資料で echo -e が「エスケープを解釈するスイッチ」として紹介されますが、POSIXのechoはオプションを定義していません。つまり -e の意味は規格外で、実装ごとに解釈が異なるか、まったく解釈されない可能性があります。実際、ある環境では echo -e '\n' が改行として扱われ、別の環境では -e \n という文字列のまま出力されます。
結論として、移植性が必要なスクリプトで echo -e に頼るのはNG です。

まず確認すること

  • どのシェルで実行しているか(bash / dash / zsh / busybox sh など)
  • echo はビルトインか外部コマンドか type -a echo # "echo is a shell builtin" ならビルトイン command -v echo # パス解決
  • 期待するエスケープ(\n \t \033 など)が本当に展開されるか

Bashの拡張と xpg_echo(挙動が変わるスイッチ)

Bashの echo は互換目的で -n/-e/-E に対応しますが、xpg_echo というシェルオプションの有無で挙動が変わることがあります。環境によっては -e を付けなくてもバックスラッシュが展開される 挙動に切り替わるため、チーム内で「効いた/効かない」の食い違いが起きやすいポイントです。

# 現在の設定を確認
shopt -p xpg_echo   # shopt -u xpg_echo なら無効、-s なら有効

# Bash組み込みのヘルプで対応オプションを確認
help echo

Bash前提のスクリプトであっても、xpg_echo の状態が違うだけで結果が変わる可能性があります。CIや本番環境での「再現性」を重視するなら、echo ではなく**printf で明示的に制御**するのが確実です。

シェル/実装差のクイック比較

  • bash-e/-E 対応。xpg_echo でデフォルト解釈が変わることがある。
  • dash(/bin/shに採用されがち)-e 非対応のケースが多い。
  • zsh:互換モードや設定で挙動が変化し得る。
  • busybox sh:組み込み機能が最小限で、-e に非対応な構成も。
  • /bin/echo(外部コマンド):GNU Coreutils等でもビルトインと挙動差が出ることがある。

実務TIP
スクリプトの先頭で「実行シェルを固定」し、テストは想定する最小機能シェルで行うのが安全。Debian/Ubuntu系で /bin/shdash のとき、echo -e突然効かなくなる例は定番です。

可搬性重視なら printf へ——置換レシピ集

echo -e をすべて printf に置き換えると、改行やエスケープの有無を常に明示でき、実装差で崩れません。最低限これだけ覚えておけばOKです。

  • 改行ありの基本 printf '%s\n' "Hello, World"
  • 改行なし printf '%s' "TOKEN="
  • 先頭がハイフンの文字列(オプション誤解釈回避) s="-e is not an option" printf '%s\n' -- "$s"
  • タブや改行などの制御文字(広く通る表現だけ使う) printf 'line1\nline2\t(col)\n'
  • 色(ANSIエスケープ)
    POSIX寄りにするなら 八進でESCを表現すると堅いです(\033)。 printf '\033[31m%s\033[0m\n' "ERROR"
  • ファイルに安全に書く(クォートと追記/上書きを明示) out="/var/log/my app/output.log" printf '%s\n' "ok" >> "$out"

「効かない」ときのチェックリスト

  • type -a echo でビルトイン/外部を確認
  • help echo(Bash)で -e/-E の扱いを読む
  • shopt -p xpg_echo の状態をそろえる
  • それでも再現性が必要なら**printfに寄せる**(特にCI・本番)

echo -e手早い一方で、環境差と長期運用の再現性という視点ではリスクが大きい選択です。**「人に見せるログ → echo」「機械が読む出力 → printf」**とざっくり切り分け、迷う状況は printf へ寄せる——これが実務での定番解です。

エスケープシーケンス完全ガイド

よく使うエスケープと実例(安全な書き方つき)

制御文字や特殊文字は、echo -e ではなく printf で明示すると誤動作を避けられます。まずは用途別の代表例を押さえましょう。

  • 改行:'\n'(行を区切る)
  • タブ:'\t'(列ぞろえ)
  • バックスラッシュ:'\\'
  • ベル:'\a'(通知音)
  • 復帰:'\r'(行頭に戻る・上書き)
  • 縦タブ:'\v'、改ページ:'\f'
  • 8進数'\0nnn'(例 \012 は改行)
  • 16進'\xHH'(例 \x41A
  • Unicode'\uHHHH' / '\UHHHHHHHH'(BMP/補助面)
# 改行・タブ・バックスラッシュ
printf 'line1\nline2\tpath\\to\\dir\n'

# 8進/16進/Unicode
printf '\012'          # => 改行
printf '\x41\n'        # => A
printf '\u3042\n'      # => あ
printf '\U0001F680\n'  # => 🚀

# 復帰で同じ行を書き換える進捗表示
for i in 0 20 40 60 80 100; do
  printf '\rprogress: %3s%%' "$i"
  sleep 0.1
done
printf '\n'

echo -e で同様のことを試すと、環境によってはエスケープが展開されない-e 自体が出力される、\xHH が解釈されない、といった差が出ます。ログや人向けのメッセージは echo、機械が読む厳密な出力は printf——この切り分けが最もトラブルを減らします。

補足
\c(ここで出力終了)を echo -e で使える環境もありますが、非移植です。改行なしは printf '%s' を選びましょう。

認識されない場合のチェック手順

\n が改行にならない」「\x1b がそのまま出てしまう」など、想定どおりに解釈されないときは、次の順で原因を切り分けます。

  1. echo の実体を確認 type -a echo # builtin か /bin/echo か help echo # bash の場合、対応オプションを確認 ビルトインと外部コマンドで挙動差があります。
  2. xpg_echo の状態を確認(bash) shopt -p xpg_echo # -s なら XPG 互換挙動で解釈が変わる チームやCI環境でここが違うと、同じスクリプトでも結果が変わることがあります。
  3. printf での再現確認(基準を作る) printf '%b\n' "A\nB\tC" # %b はエスケープ解釈 printf '\x41\n' # 16進 printf '\033[31mRED\033[0m\n' # ESC を八進で表現 printf で期待どおりなら、echo 側の問題と判断できます。
  4. ANSI-C クォート $'...' の可否を把握 printf $'A\nB\tC\n' # bash/zsh では可、POSIX 非準拠 便利ですが移植性は落ちるため、共有スクリプトには推奨しません。
  5. ロケール・フォントの影響を除外
    Unicode絵文字や結合文字は、端末側で表示されないことがあります。LC_CTYPE をUTF-8にし、別のターミナルでも確認します。
  6. クォートと展開の順序を見直す echo "\x41" # echo -e でも \x41 が解釈されない環境あり printf '\x41\n' # こちらなら確実に A 文字列は必ずクォートし、シェル展開(*$var)の混入を疑います。

テスト時は、目視しづらい制御文字を可視化すると診断が楽です。

# 改行やタブを可視化して比較
printf 'A\nB\tC\n' | od -An -t x1
# 0a(改行)/ 09(タブ)が入っているかをバイトで確認

この流れで原因を特定し、本番やCIなど再現性が重要な場所では printf を基準に置くと、環境差に悩まされません。

ANSIカラーの安全な出し方

\e より \x1b/3 を使う(環境差を抑える)

端末の色付けは ESC(0x1B)+制御列で行います。書き方は複数ありますが、\x1b(16進)や \033(8進) の方が移植性が高く、\e はシェル依存で解釈されないことがあります。さらに、出力は echo -e ではなく printf で行うと誤解釈を避けられます。

# 赤で「ERROR」を出してリセット
printf '\x1b[31m%s\x1b[0m\n' "ERROR"
# 同義(八進)
printf '\033[31m%s\033[0m\n' "ERROR"

代表的な色コード(前景色)は次のとおりです。

  • 30: 黒 / 31: 赤 / 32: 緑 / 33: 黄 / 34: 青 / 35: マゼンタ / 36: シアン / 37: 白
  • 明るい色は 90–97、太字は 1、下線は 4、リセットは 0
printf '\033[1;32m%s\033[0m\n' "SUCCESS"   # 太字+緑
printf '\033[4;34m%s\033[0m\n' "LINK"      # 下線+青

使い回せるテンプレ(関数・変数で管理)

毎回シーケンスを書くのは冗長なので、変数や関数にまとめると保守が楽です。

ESC=$'\033'            # ANSI-Cクォート(bash/zsh向け)
RED="${ESC}[31m"; GREEN="${ESC}[32m"
BOLD="${ESC}[1m"; RESET="${ESC}[0m"

log_ok()    { printf '%s%s%s\n' "$GREEN" "$*" "$RESET"; }
log_err()   { printf '%s%s%s\n' "$RED"   "$*" "$RESET"; }
log_title() { printf '%s%s%s\n' "$BOLD"  "$*" "$RESET"; }

log_title "Deploy"
log_ok    "Completed"
log_err   "Failed"

ANSI-Cクォート $'...' が使えない環境を想定するなら、ESC="$(printf '\033')" のように初期化しても構いません。出力側は常に printf に統一します。

“色を出すべきときだけ”出す(TTY判定・無効化フラグ)

CIやリダイレクト先のログではカラーがノイズになります。標準出力がTTYかを判定し、色を自動で無効化すると親切です。

enable_color=0
if [ -t 1 ]; then
  enable_color=1
fi

color() {
  if [ "$enable_color" -eq 1 ]; then
    printf '%b' "$1"
  fi
}

color "$RED";  printf '%s' "ERROR: "
color "$RESET"; printf '%s\n' "something wrong"

明示的に切りたいユーザー向けに、NO_COLOR 環境変数(慣習)で無効化できる実装にしておくのも実務で好評です。

if [ -n "${NO_COLOR:-}" ] || [ ! -t 1 ]; then
  RED=""; GREEN=""; BOLD=""; RESET=""
fi

“色を剥がす”ユーティリティ

外部コマンドの出力に色が混ざって困るときは、制御列を除去します。

# ANSIエスケープを削除(posix-awkで動く簡易版)
strip_ansi() { awk '{gsub(/\033\[[0-9;]*[A-Za-z]/,"")}1'; }
some_cmd | strip_ansi > plain.log

ログを解析するパイプラインでは、付ける/剥がすをテンプレ化しておくと、誰が触れても安定します。

実務でハマる落とし穴と対策

グロブ展開とクォート(echo * と echo "*")

echo *シェルが先に展開し、カレントディレクトリのファイル名一覧を出力します。* そのものを表示したい、または存在するファイル名に引っ張られたくない場合はクォート必須です。

echo *        # => file1 file2 ...(実在ファイルに展開)
echo "*"      # => *(リテラル)
echo *.log    # => *.log が存在すれば展開、なければパターンが残るシェルも
  • 原則:ワイルドカードや空白・日本語・$ を含む文字列はダブルクォートで囲む。
  • find/grep連携echo "$pattern" のように常に引用して、意図しない分割・展開を防ぐ。
  • 未一致時に残るか空文字になるかはシェル差があります(zsh は NULL_GLOB などの設定で変化)。**「残ってほしくない」**なら、printf で固定出力にするのが安全です。

ビルトインと /bin/echo の違い(実体確認)

echo は多くのシェルで組み込みです。/bin/echo(外部コマンド)と挙動差が出る場面があり、-e の扱いやエスケープ解釈で食い違うことも。

type -a echo
# echo is a shell builtin
# echo is /bin/echo   ← 外部コマンドも存在する場合

# 明示的に外部コマンドを使う(検証時)
/bin/echo -e "A\nB"
  • スクリプト内の混在に注意:builtin echo .../bin/echo ...混在すると、テスト時と本番で挙動がズレる典型事例。
  • CIで固定:実体をどちらかに統一(推奨はビルトイン+printf)し、shellcheck などでルール化すると再発防止になります。

エラーは標準エラーへ(>&2)

ログ収集や監視と連携するなら、正常系はstdout、異常系はstderrに分けるのが実務の基本です。

# 正常系(標準出力)
printf '%s\n' "ready"

# 異常系(標準エラー)
printf '%s\n' "ERROR: config not found" >&2
  • パイプラインに優しいsome_cmd | wc -l のような処理で、stderrをノイズにしない
  • リダイレクト設計:アプリでは 1>out.log 2>err.log のように出力先を分離でき、解析が簡単。
  • 終了コードecho/printf 自体は 0 を返しがち。return/exit とセットでエラーを伝える習慣も重要です。

まとめの指針

見せたい文字列は必ずクォート
echo の実体を把握(ビルトイン前提+printf基準)
stderrを正しく使う(機械処理の再現性を高める)

【Windows CMD】ECHOの基本とバッチ実務

echo on/off と現在設定の確認、@echo off の意味

Windowsの ECHO には「メッセージ表示」と「コマンドエコー制御」の二つの役割があります。
echo on/echo off実行中のコマンドを表示するかを切り替え、echo 単体は現在の状態を表示します。バッチの先頭でよく見る @echo off は、この行だけ出力を抑制しつつ、以降のコマンドエコーもまとめて非表示にする慣用句です。

@echo off
echo Start processing...
rem ここから先、コマンド自体は表示されない

空行の出し方と安全策(echo. / echo()

空行を出す定番は echo. ですが、まれな文脈で誤動作するケースがあるため、より頑健なのは echo( です(( はファイル名に使えず衝突しにくい)。

echo(            rem ← 空行を1つ出力(推奨)
echo.            rem ← 多くの場面で動くが、環境依存の稀な罠あり

特殊文字のエスケープ(^ と %%)

パイプやリダイレクトなどメタ文字をそのまま表示したい場合は ^ を前置します。環境変数の %バッチ内では %% に二重化が必要です。

echo ^| ^& ^> ^< ^^  (パイプ/AND/リダイレクト/キャレットの表示)
set NAME=World
echo Hello %%NAME%%   rem => Hello %NAME%

変数が空のときの「ECHO はオフです。」を避ける

echo %VAR%%VAR% が空だと、状態表示のほうが優先されて
**「ECHO はオフです。」**と出ることがあります。次の書き方で回避します。

echo:%VAR%           rem 先頭にリテラルを置いて状態表示を回避
rem 遅延展開を使う方法(必要なら)
setlocal enabledelayedexpansion
echo(!VAR!           rem !VAR! を使うと未定義時も安全
endlocal

改行なしで出す(set /p テクニック)

CMDには echo -n 相当がありません。標準入力からの読み取りを利用して、
改行なし出力を実現します。

<nul set /p "=TOKEN="   rem 改行なしで TOKEN= を出力
type token.txt          rem 後続の出力が同じ行に続く
rem 改行が欲しいタイミングで
echo(

ちょい便利:色付き表示(CMD)

純正CMDでも簡易な色付けは可能です。colorコンソール全体の配色を変え、^[[...m のANSIはWindows 10以降のVT対応が有効なら使えます(必要に応じて reg add ... VirtualTerminalLevel などの有効化が必要な場合あり)。バッチは運用環境差が出やすいため、まずは色なし前提で運用し、必要な場面だけ条件付きで色を付けるのが無難です。

rem 全体の配色(前景/背景)
color 0A  rem 黒地に明るい緑

目的別チートシート(Linux/UNIX & Windows)

Linux/UNIX の定番レシピ(コピペOK)

  • 改行ありで出す(安全) printf '%s\n' "Hello, World"
  • 改行なしで連結 printf '%s' "TOKEN="; cat token.txt
  • タブや改行を含める printf 'A\tB\nC\n'
  • 先頭がハイフンの文字列を安全に出す s="-n is not option" printf '%s\n' -- "$s"
  • ANSIカラー(赤→出力→リセット) printf '\033[31m%s\033[0m\n' "ERROR"
  • stderr へ出す(ログ分離) printf '%s\n' "ERROR: not found" >&2
  • ファイルへ上書き/追記 printf '%s\n' "line" > file.txt printf '%s\n' "more" >> file.txt
  • 原子的に置換(設定ファイルなど) tmp=$(mktemp) printf '%s\n' "key=value" > "$tmp" install -m 0644 "$tmp" /etc/myapp.conf rm -f "$tmp"
  • ワイルドカードを文字として出す printf '%s\n' "*"
  • 不可視文字をバイトで確認 printf 'A\tB\n' | od -An -t x1
  • 空行を出す printf '\n'
  • 改行を上書きして進捗表示 for i in 0 25 50 75 100; do printf '\rprogress: %3s%%' "$i"; sleep 0.1 done; printf '\n'

Windows CMD の定番レシピ(コピペOK)

  • コマンドエコー抑止+開始メッセージ @echo off echo Start...
  • 空行を出す(安全策) echo(
  • 改行なしで出す(set /p 技) <nul set /p "=TOKEN="
  • パイプ等のメタ文字を表示 echo ^| ^& ^> ^< ^^
  • 未定義変数でも安全に表示 echo:%VAR%
  • 標準出力/標準エラーを分ける echo ok 1>> out.log echo error 1>&2
  • ログに追記しつつ画面表示(PowerShell併用不要の簡易形) somecmd | tee -a logfile.txt rem ※ Windows 11 等の新環境で利用可能な tee コマンド前提

よくある質問(FAQ)

Q1. echo -e が効いたり効かなかったりします。どうすれば?

  • POSIXでは echo にオプションがないため、-e は非規格です。
  • シェル・実装差(bash/dash//bin/echo/xpg_echo など)で挙動が変わります。
  • 解決策:機械が読む出力は printf を基準に。printf '%b\n' 'A\nB' のように明示します。

Q2. 改行なしで安全に出すには?

  • Linux/UNIX:printf '%s' "TEXT" が確実。
  • Windows CMD:<nul set /p "=TEXT" を使います。

Q3. 先頭が - の文字列がオプションと誤認されます。

  • Linux/UNIX:printf '%s\n' -- "$str" を使うと安全。
  • echo を使うなら echo -- "$str" で回避できる場合もありますが、実装差が残ります。

Q4. echo * がファイル名に展開されてしまいます。

  • クォートで抑止:echo "*"
  • 機械処理では printf '%s\n' '*' が確実。

Q5. 色付けは \e と 3 のどちらが良い?

  • **\033(8進)や \x1b(16進)**がより移植的。echo -e ではなく printf で出力しましょう。

Q6. ログで通常出力とエラーを分けたい。

  • Linux/UNIX:printf '%s\n' "msg" >> app.log、エラーは >&2
  • Windows:1>2> を使い分ける。監視や集計で差が出ます。

Q7. CI など環境で色を無効化したい。

  • Linux/UNIX:[ -t 1 ] || NO_COLOR=1 などで TTY 判定NO_COLOR を見て色変数を空に。
  • Windows:条件付きで color を呼ばない、VT無効環境ではANSI制御を出さない実装にします。

Q8. /bin/echo とビルトイン echo の違いで事故ります。

  • まず type -a echo実体を確認。
  • プロジェクト方針として 「ビルトイン+printf」に統一し、テストも同条件に合わせるのが無難です。

参考・参照リンク

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント