第10回 終了ステータスを理解しよう:$?とコマンドの成功・失敗の仕組み | はじめてのシェルスクリプト

* 当サイトでは、コンテンツの一部に広告を掲載しています。

System Note $ cat /proc/ai-disclosure

本記事の構成および論理分析にはAI(人工知能)を使用しています。情報の正確性は、システム管理者(UNIXユーザー)による手動検証済みです。

第10回 終了ステータスを理解しよう:$?とコマンドの成功・失敗の仕組み | はじめてのシェルスクリプト
目次

はじめに

この連載では、macOS のターミナルで sh を使いながら、シェルスクリプトの基本を順番に学んでいきます。

第8回・第9回では、if 文と条件式を使って「条件によって処理を分ける」方法を学びました。条件分岐はシェルスクリプトの核心のひとつです。

実は、シェルが「条件が成り立った」「成り立たなかった」を判断するとき、その根拠になっているのが「終了ステータス」という数値です。コマンドが成功したのか、失敗したのか——その結果を数値として表し、スクリプトの流れを制御するために使います。

第10回では、終了ステータスとは何か、$? でどう確認するか、そしてコマンドの結果を使って処理を分岐する考え方を学びます。この仕組みを理解すると、エラー処理や安全なスクリプトを書くための土台が整いますよ。

この回で学ぶこと

  • 終了ステータスとは何か
  • 0 は成功であること
  • 失敗時の考え方
  • $? で直前の結果を確認する方法
  • コマンドの結果を使って分岐する考え方
  • 成功と失敗で表示が変わる例
  • 初学者が誤解しやすい点

終了ステータスとは何か

コマンドの結果を表す数値

シェルでは、コマンドを実行すると、その結果が数値で返されます。

この数値を終了ステータスと呼びます。

0 は成功

終了ステータスでは、0 が成功を意味します。

これは初学者が誤解しやすい点ですが、通常の感覚とは逆で、0 が正常終了です。

0 以外は失敗

1 などの 0 以外の値は、失敗や異常な状態を表します。

何が原因の失敗かはコマンドによって異なりますが、まずは「0 は成功、それ以外は失敗」と理解すれば十分です。

$? で直前の結果を確認する

直前に実行したコマンドの終了ステータスは、$? で確認できます。

たとえば、次のように使います。

ls
echo $?

ls が成功すれば、echo $? の結果は 0 になります。

存在しないファイルを指定した場合は、0 以外の値になります。

サンプルコード

status_sample.sh に次の内容を保存します。

#!/bin/sh

ls README.md
echo "Status: $?"

ls no_such_file.txt
echo "Status: $?"

実行手順

1. ファイルを作成して保存する

エディタで status_sample.sh という名前のファイルを作成し、次の内容を保存します。

#!/bin/sh

ls README.md
echo "Status: $?"

ls no_such_file.txt
echo "Status: $?"

2. スクリプトを実行する

次のコマンドを実行します。

sh status_sample.sh

実行結果の例です。

README.md
Status: 0
ls: no_such_file.txt: No such file or directory
Status: 1

この例では、README.md は存在するので最初の ls は成功し、終了ステータスは 0 です。

一方、no_such_file.txt は存在しないので、2つ目の ls は失敗し、終了ステータスは 1 になります。

コードの読み方

ls README.md

このコマンドは、README.md というファイルを表示します。

ファイルが存在すれば成功です。

echo “Status: $?”

$? は、直前のコマンドの終了ステータスです。

ここでは、直前の ls の結果を表示しています。

ls no_such_file.txt

存在しないファイルを指定しているため、このコマンドは失敗します。

そのため、直後の $?0 以外になります。

終了ステータスを使って分岐する

終了ステータスは、if 文でそのまま使えます。

たとえば、次のように書けます。

if ls README.md > /dev/null 2>&1; then
  echo "File found"
else
  echo "File not found"
fi

ls README.md が成功すれば then 側、失敗すれば else 側が実行されます。

初学者がつまずきやすい点

0 を失敗だと思ってしまう

終了ステータスでは、0 は成功です。

これは最初に必ず押さえておく必要があります。

$? を確認する前に別のコマンドを実行してしまう

$? は直前のコマンドの結果です。

間に別のコマンドを挟むと、その結果で上書きされます。

エラーメッセージと終了ステータスを別に考えられない

画面にエラーメッセージが出た場合、多くは終了ステータスも 0 以外になります。

表示だけでなく、$? も合わせて確認すると判断しやすくなります。

よくあるエラー

echo $? の結果が思ったものと違う

$? を確認する前に別のコマンドを実行していないか確認してください。

直前のコマンドだけが対象です。

成功したのに分岐しない

if の条件に使っているコマンド自体を見直してください。

成功するはずのコマンドが、実際には失敗している可能性があります。

失敗したのに原因が分からない

画面に表示されるエラーメッセージと、$? の両方を確認してください。

練習用コード

次の内容で status_check.sh を作成して実行してみてください。

#!/bin/sh

if ls next_task.txt > /dev/null 2>&1; then
  echo "next_task.txt exists"
else
  echo "next_task.txt does not exist"
fi

echo "Last status: $?"

次に、next_task.txt を別の名前に書き換えて試し、表示がどう変わるか確認してください。

この回で理解しておくこと

  • 終了ステータスはコマンドの結果を表す数値である
  • 0 は成功、0 以外は失敗を表す
  • $? で直前のコマンド結果を確認できる
  • 終了ステータスは if 文の分岐に使える
  • エラーメッセージと終了ステータスを合わせて確認すると分かりやすい
  • $? は別のコマンドを実行すると上書きされる

まとめ

今回は、終了ステータスの基本として、0 が成功であること、$? で直前の結果を確認する方法、結果を分岐に使う考え方を学びました。

終了ステータスを理解すると、コマンドの成功と失敗を基準にしたスクリプトを書きやすくなります。

次回は、for 文で繰り返し処理を行う方法を学びます。

次回予告

次回は「for文で繰り返し処理をしてみよう」です。

複数の値を順番に処理する基本を確認します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

のいのアバター のい UNIX Cafe マスター

Macintosh Color Classicから始まった旅は、長いWindows時代を経て、Windows10のサポート終了をきっかけにUNIXの世界へ戻ってきました。UNIX Cafeでは、UNIX・Linux・そしてMacな世界を、むずかしい言葉を使わず、物語のように書いています。プログラミングは、アイデアをコンピューターに伝えるための言葉です。簡単な単語と文法を覚えれば、誰でもコマンドを使えます。ぜひ一度、やさしいプログラミングの世界をのぞいてみてください。

Created by UNIX Cafe

目次