トップ > Linuxらしい使い方を覚える >
シェル変数と環境変数でシェルやコマンドの振る舞いを制御

  

シェル変数と環境変数を学ぶ

シェルに関する解説はまだまだ続きます。 続いて解説するのは "シェル変数" と "環境変数" です。 どちらも 変数(へんすう) へんすう 変数(へんすう) と呼ばれるものですが、有効範囲が異なります。 有効範囲とは何なのか、については後ほど解説します

まずは、変数とは何なのかを説明しなくてはなりません。 変数というのは、情報を格納することができる箱のようなものです。 新たに箱を用意して中に情報を格納し、必要な時に箱の中の情報を確認し、また必要があれば箱の中身を入れ替え、不要になったら箱ごと捨てる、というような感覚で変数を使うことができます。

では、変数は何のために使われるのでしょうか。 1つ目は各種アプリケーションやコマンドの振る舞いをカスタマイズするためです。 例えば LANG という名前の変数をカスタマイズすることで、各種アプリケーションやコマンドを英語表記にすることができます。 つまり、メニュー項目やボタンなどが英語になる、というわけです。 各種アプリケーションやコマンドが変数 LANG の中身を見て振る舞いを変えるためです。

2つ目はシェルの振る舞いをカスタマイズするためです。 例えば PS1 という名前の変数は、シェルプロンプトの表示内容を設定するために使われます。 変数 PS1 に格納されている値を書き換えることで、シェルプロンプトの表示内容をカスタマイズすることができるのです。 これも同じくシェルが変数 PS1 の中身を見て振る舞いを変えているためです。

3つ目は何らかの情報を格納し、後で参照するためです。 利用者に何かを入力させ、後の工程で入力内容を参照する、という具合です。


では、変数を使って色々と試してみましょう。 端末を開き、キーボードから date と入力して、Enterキーを押してください。


date

 

以下のように日本語で日時が表示されます。

taro@myhostname:~$ date
2024年  6月 13日 木曜日 15:12:35 JST
taro@myhostname:~$

date コマンドが日本語で日時を表示したのは、変数 LANG が日本語を表示するための設定になっているからです。

では、変数 LANG にはどんな値が格納されているのでしょうか。 確認してみましょう。 キーボードから echo $LANG と入力して、Enterキーを押してください。


echo $LANG

 
  
変数名の前に $(ドル記号) を付ける必要があります。

以下のように "ja_JP.UTF-8" と表示されます。 変数 LANG には "ja_JP.UTF-8" が格納されていることがわかりました。

itaro@myhostname:~$ echo $LANG
ja_JP.UTF-8
taro@myhostname:~$

このように、変数名の前に $(ドル記号) を付けることで中身を参照することができます。

  
ja_JP.UTF-8 は ja が日本語 JP が日本国 UTF-8 が文字エンコーディング(コンピュータ内で文字を数値化する規格)をUTF-8とする、ということを表しています。
  
変数 LANG に "ja_JP.UTF-8" が設定されているのは、Linux Mintのインストール時に言語に "日本語" を選択したためです。

ではここで、変数 LANG の中身を書き換えてみましょう。 キーボードから LANG=en_US と入力して、Enterキーを押してください。


LANG=en_US

 
  
変数に新たな情報を格納することを 代入(だいにゅう) だいにゅう 代入(だいにゅう) といいます。 代入では変数名の前に $(ドル記号) を付けてはいけません。 また =(イコール) の前後に空白を入れてもいけません
  
en_US は en が英語 US が米国を意味しています。

以下のように見た目には何も起こりませんが、大丈夫です。

taro@myhostname:~$ LANG=en_US
taro@myhostname:~$

では、再度 date コマンドを実行してみましょう。 キーボードから date と入力して、Enterキーを押してください。


date

 

以下のように日時の表示が英語に変化しました。 date コマンドが変数 LANG を参照し、対応する言語で日時を表示してくれました。

taro@myhostname:~$ date
Thu Jun 13 15:47:52 JST 2024

このように変数の値を書き換えることで、コマンドの振る舞いを変えることができます。 今回は date コマンドの例を紹介しましたが、シェルでも同じように変数を使ってカスタマイズすることができます。 GIMP などのX Window System上のアプリケーションでも同様です。

  
変数 LANG の値は、端末を開き直すと "ja_JP.UTF-8" に戻ります。 変数の値を手作業で戻す必要はありません。

ここで、変数 PATH について紹介しておきます。 この変数はシェルが参照するもので、コマンドや各種アプリケーションを探し出すディレクトリを定義するためのものです。

この記事では date コマンドを何度か実行しましたが、このコマンドはシェルに組み込まれている組み込みコマンド(ビルトインコマンド)ではありません。 つまり、ファイルとしてディレクトリツリー上のどこかに存在しています。

どこに存在しているのか確認してみましょう。 キーボードから which date と入力して、Enterキーを押してください。


which date

 
  
which コマンドは、引数として渡されたアプリケーションやコマンドの場所を探し出すためのものです。

以下のように date コマンドの正体は /usr/bin/date というファイルであることがわかります。

taro@myhostname:~$ which date
/usr/bin/date
taro@myhostname:~$

しかしこれまで、

/usr/bin/date

と打ち込んで実行したことは一度もありません。 毎回のように、

date

と打ち込むだけで実行することができました。 なぜでしょうか。 その秘密が変数 PATH に隠されています

では、変数 PATH の値を見てみましょう。 キーボードから echo $PATH と入力して、Enterキーを押してください。


echo $PATH

 

以下のように :(コロン) で区切られた複数のディレクトリパスが表示されます。

taro@myhostname:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
taro@myhostname:~$

シェルは、利用者が入力したコマンドを上の複数のディレクトリパスの中から探し出そうとします。 まずは /usr/local/sbin を探し、なければ次の /usr/local/bin を探し、それでもなければ /usr/sbin を探す、という具合にです。 もちろん、見つかった時点でそのコマンドを実行します。

date コマンドを実行するのに、

date

と打ち込むだけで済んでいるのは、変数 PATH のおかげなのです。


シェルが参照する別の変数も紹介しておきます。 シェルプロンプトの表示内容をカスタマイズするための変数 PS1 です。

試しに、シェルプロンプトにはカレントディレクトリだけが表示されるようにしてみましょう。 キーボードから PS1='\W ' と入力して、Enterキーを押してください。


PS1='\W '

 
  
\ はバックスラッシュです。 バックスラッシュはUNIX系OSでは \(バックスラッシュ) として正しく表示されますが、Windows では ¥(円マーク) として表示されます。 どちらにしても、日本語キーボードからは ¥(円マーク) で入力します。
  
ウェブ上でのバックスラッシュの表示は、ウェブブラウザによって異なります。 \(バックスラッシュ) として表示するものもあれば ¥(円マーク) として表示されるものもあります。

以下のようにシェルプロンプトがカレントディレクトリのみの表示に変化します。

taro@myhostname:~$ PS1='\W '
~  

このように変数 PS1 の値を変えることでシェルプロンプトの表示内容をカスタマイズすることができます。

では、シェルプロンプトの表示内容を元に戻しておきましょう。 シェルプロンプトは端末を開き直すと元の表示内容に戻りますが、今回は端末を開いたまま戻してみましょう。 キーボードから . ~/.bashrc と入力して、Enterキーを押してください。


. ~/.bashrc

 

以下のようにシェルプロンプトが元の表示に戻ります。

~ . ~/.bashrc
taro@myhostname:~$

.(ピリオド) は、引数として渡されたファイルを実行するための命令です。 今回は ~/.bashrc というファイルを渡していますので、ホームディレクトリの .bashrc というファイルが実行されました。

ホームディレクトリの .bashrc ファイルは "シェルファイル" に分類されるファイルで、簡単に言えばシェルの設定を行うためのファイルです。 このファイルの中にシェルプロンプトを初期設定する記述があるため、シェルプロンプトの表示内容が元に戻りました。


シェルが参照する変数を最後にもう1つだけ紹介しておきます。 ホームディレクトリのディレクトリパスが格納されている変数 HOME です。

変数 HOME の中身を確認してみましょう。 キーボードから echo $HOME と入力して、Enterキーを押してください。


echo $HOME

 

以下のように "/home/taro" と表示されます。 ホームディレクトリのディレクトリパスが格納されています。

taro@myhostname:~$ echo $HOME
/home/taro
taro@myhostname:~$

ではここで ~(チルダ) がホームディレクトリを表していたことを思い出してください。 例えば、ホームディレクトリの下の Documents ディレクトリへ移動するなら、

cd ~/Documents

と実行することで、ホームディレクトリの下の Documents ディレクトリへ移動することができます。

実は ~(チルダ) はシェルによって展開されます。 何に展開されるのか。 それが $HOME です。

試しに ~(チルダ) をecho コマンドで表示させてみましょう。 キーボードから echo ~ と入力して、Enterキーを押してください。


echo ~

 

以下のように "/home/taro" と表示されます。 $HOME と同じ値です。

taro@myhostname:~$ echo ~
/home/taro
taro@myhostname:~$

このように、コマンドラインで入力した ~(チルダ) は $HOME に置き換えられます。 $HOME と打ち込むには 5回のキーストロークが必要ですが ~(チルダ) なら1回で済ませることができます。


では次に、キーボードからの入力を変数に格納し、その内容を後で参照する、ということを試してみましょう。 キーボード(標準入力)からの入力を変数に格納するためのコマンドが read コマンドです。

キーボードから read MYINPUTVALUE と入力して、Enterキーを押してください。


read MYINPUTVALUE

 

以下のように入力待ちになります。 何かテキストを入力してEnterキーを押す必要があります。

taro@myhostname:~$ read MYINPUTVALUE
 

以下のように好きなテキストを入力してEnterキーを押してください。 read コマンドが終了し、シェルプロンプトに戻ります。

taro@myhostname:~$ read MYINPUTVALUE
Hello World
taro@myhostname:~$

では、変数 MYINPUTVALUE の内容を確認してみましょう。 キーボードから echo $MYINPUTVALUE と入力して、Enterキーを押してください。


echo $MYINPUTVALUE

 

以下のように入力した内容が保存されていたことがわかります。

taro@myhostname:~$ echo $MYINPUTVALUE
Hello World
taro@myhostname:~$

このように変数は後で参照するために情報を格納する、という目的のためにも使用することができます。

変数を削除するには

上で解説したように、変数に値を代入するには、

MYNAME=yamada

と実行します。 これにより、変数 MYNAME に "yamada" というテキストが格納されます。 変数 MYNAME が存在していれば中身が上書きされ、存在していなければ変数が新たに作成されます。

では、変数の削除はどうすればいいのでしょうか。 変数を削除するには、

unset MYNAME

と実行します。 変数名の前に $(ドル記号) を付けてはいけません

以下が変数 MYNAME の作成から削除までの実行例です。

taro@myhostname:~$ echo $MYNAME

taro@myhostname:~$ MYNAME=yamada
taro@myhostname:~$ echo $MYNAME
yamada
taro@myhostname:~$ unset MYNAME
taro@myhostname:~$ echo $MYNAME

taro@myhostname:~$

システム変数とユーザ変数

変数には HOME や PATH や PS1 や LANG のように、あらかじめ用途が決められているものがあります。 それらを "システム変数" と呼びます。

一方、変数 MYINPUTVALUE のように利用者が必要に応じて準備する変数は "ユーザ変数" と呼ばれます。

あくまでも呼び名の違いであり、利用手順やコンピュータ内での振る舞いなどは何も違いはありません

変数は${MYNAME}でも参照できる

何度も説明しているように、変数に値を代入するには、

MYNAME=yamada

と記述し、変数の中身を参照するには、

echo $MYNAME

と記述します。

実は変数を参照するための別の記述方法もあり、

echo ${MYNAME}

と記述することもできます。 どちらも全く同じ結果になります

記述の使い分け

$MYNAME と ${MYNAME} の結果が同じなら、どちらの記述を採用しても違いはないのでしょうか。 実は、$MYNAME という記述では問題が起こることがあります

その問題を実感してみましょう。 端末を開き、キーボードから SPEED=10 ; echo $SPEEDkm と入力して、Enterキーを押してください。


SPEED=10 ; echo $SPEEDkm

 

以下のように何も表示されません

taro@myhostname:~$ SPEED=10 ; echo $SPEEDkm

taro@myhostname:~$

理由はもちろん、"$SPEEDkm" という記述を "変数 SPEEDkm の参照" のことだとシェルが理解したためです。 変数 SPEEDkm なんてものは存在しませんから、何も表示されません。

では、記述を変えて実行してみましょう。 キーボードから SPEED=10 ; echo ${SPEED}km と入力して、Enterキーを押してください。


SPEED=10 ; echo ${SPEED}km

 

以下のように狙った通りの結果になりました。

taro@myhostname:~$ SPEED=10 ; echo ${SPEED}km
10km
taro@myhostname:~$

変数名を {}(波括弧) で括ったことで、正しい変数名をシェルに伝えることができました。


どう使い分けるかですが、これは好みの問題もあると思います。 筆者は基本的には $MYNAME と記述し、今回の例のように問題が発生する場合のみ ${MYNAME} と記述しています。 {}(波括弧) はキーボードから入力しやすい文字ではありませんので、あまり使いたくないのです。

常に ${MYNAME} と記述する、という方もたくさんいることでしょう。 記述が統一されるという利点があります。

シェル変数と環境変数とは

最初に説明したように、変数には "シェル変数" と "環境変数" があります。 どちらも変数であることには変わりありませんが有効範囲が異なります

"シェル変数" というのは、シェル内でしか参照できない変数のことです。 シェルから呼び出した各種コマンドには渡されません

一方、シェルから呼び出した各種コマンドからも参照できる変数が "環境変数" です。

シェル変数と環境変数はどう作り分けるのか

何度も解説したように、

MYNAME=yamada

と実行することで変数 MYNAME に "yamada" というテキストを格納することができます。

  
変数 MYNAME が存在していれば中身が上書きされ、存在していなければ変数が新たに作成されます。

では、新たに変数が作成された場合には、その変数はシェル変数になるのでしょうか、それとも環境変数になるのでしょうか。 答えは、シェル変数です。 それなら、環境変数はどうやって作成するのでしょうか。

環境変数を作成するには、作成済みのシェル変数に環境属性を付けるという手順を踏みます。 シェル変数に環境属性を付けると環境変数に変化する、ということです。

シェル変数に環境属性を付けるためのコマンドは export コマンドです。 以下のように、

export MYNAME

と実行することで、シェル変数 MYNAME に環境属性が付き環境変数へと変化します

逆に環境変数から環境属性を取り除く場合には、

export -n MYNAME

と実行します。 これにより、環境変数 MYNAME がシェル変数に戻ります

変数の作成と環境属性の付与を一度にまとめて、

export MYNAME=yamada

の1行で実行することもできます。 シェル変数 MYNAME に "yamada" が格納され、即座に環境変数になります。

変数の一覧を見るには

変数の一覧を表示するには、

set

と実行します。 なお、set コマンドが返す一覧にはシェル変数と環境変数の両方が含まれています

また、set コマンドの結果には変数だけでなく、シェル 関数(かんすう) かんすう 関数(かんすう) と呼ばれるものも表示されてしまいます。 シェル関数を表示しないようにするには、

(set -o posix; set)

と実行します。 これで、シェル変数と環境変数の一覧だけが表示されます

ある変数がシェル変数なのか環境変数なのか調べるには

ある変数がシェル変数なのか環境変数なのかは、

printenv

と実行することで確認することができます。 printenv コマンドを実行すると環境変数の一覧が表示されます。 この一覧に含まれていれば環境変数で、そうでなければシェル変数です。

  
env コマンドを引数無しで実行することでも、printenv コマンドと同じ結果が得られます。

シェル変数だけの一覧を見るには

printenv コマンドで環境変数だけの一覧が見れるなら、シェル変数だけの一覧はどうやって見ればいいのでしょうか。

残念ながらそんな便利なコマンドはありません。 set コマンドの結果から環境変数を除外するしかありません。 そのためには、

comm -23 <((set -o posix; set) | sort) <(printenv | sort)

と実行します。 これで、シェル変数のみの一覧が表示されます。

  
comm コマンドは、2つのファイルを比較して結果を表示します。 オプションに -23 を指定しているため、ファイル1 のみに含まれる行だけが表示されます。
  
<((set -o posix; set) | sort) と <(printenv | sort) という記述は "プロセス置換" と呼ばれます。 コマンドの実行結果をファイルとして扱えるようにするシェルの機能です。
  
comm コマンドからは (set -o posix; set) | sort の実行結果をファイル1として printenv | sort の実行結果をファイル2 として扱うことができます。

変数 LANG でちょっと遊んでみよう

ではここで、変数 LANG を使って色々と遊んでみましょう。 まずは、変数 LANG がシェル変数なのか、環境変数なのか確認してみましょう。

端末を開き、キーボードから printenv | grep LANG と入力して、Enterキーを押してください。


printenv | grep LANG

 

以下のように変数 LANG は環境変数であることがわかります。 printenv コマンドには環境変数しか表示されませんから。

taro@myhostname:~$ printenv | grep LANG
LANG=ja_JP.UTF-8
taro@myhostname:~$

では、環境変数 LANG をシェル変数に戻しましょう。 環境属性を取り除きます。 キーボードから export -n LANG と入力して、Enterキーを押してください。


export -n LANG

 

以下のように見た目には変化ありませんが、シェル変数に戻っているハズです。

taro@myhostname:~$ export -n LANG
taro@myhostname:~$

シェル変数に戻っていることを確認しましょう。 キーボードから printenv | grep LANG と入力して、Enterキーを押してください。


printenv | grep LANG

 

以下のように printenv コマンドには表示されなくなりました。

taro@myhostname:~$ printenv | grep LANG
taro@myhostname:~$

もちろん、変数そのものが削除されたわけではありません。 一応、それを確認しておきましょう。

キーボードから echo $LANG と入力して、Enterキーを押してください。


echo $LANG

 

以下のように変数 LANG はシェル変数として残っています。

taro@myhostname:~$ echo $LANG
ja_JP.UTF-8
taro@myhostname:~$

では次に、変数 LANG がシェル変数に戻ったこの状態で、date コマンドを実行してみましょう。 キーボードから date と入力して、Enterキーを押してください。


date

 

以下のように date コマンドの結果が英語表記になりました。

taro@myhostname:~$ date
Fri Jun 14 16:14:42 JST 2024
taro@myhostname:~$

英語表記になったのは変数 LANG がシェル変数に戻ったためです。 シェル変数はシェル内でしか参照できず、シェルから呼び出した各種コマンドには渡されません

date コマンドは変数 LANG を参照しようとしますが、もちろん失敗します。 そのため、どの言語で表示すればよいか判断できず、翻訳しない英語のまま表示されました。

変数名に使える文字と命名に関する慣習

変数名に使える文字は、

  1. 英字(大文字)
  2. 英字(小文字)
  3. 数字
  4. _(アンダーバー)

の4種類です。 ただし、変数名の先頭に数字を指定することはできません

なお、慣習として英字の大文字と小文字を混在させることはまずありません。 同じく慣習として、シェル変数は小文字で、環境変数は大文字で記述するのが一般的です。

  

変数に一時的な値を代入するには

しつこく書きますが、変数に値を代入するには、

NAME=value

と実行します。 変数 NAME が存在していなければ新たに作成され、存在していれば中身が上書きされます。

実は、これ以外にも変数へ値を代入するための記述方法があり、

NAME=value command

と実行することで、この1つの命令の中だけで有効になる値を代入することができます。 つまり、一時的な値です。

この一時的な代入を試してみましょう。 端末を開き、キーボードから LANG=en_US date ; date と入力して、Enterキーを押してください。


LANG=en_US date ; date

 

以下のように1行目の日時は英語で、2行目の日時は日本語で表示されます。 これは、最初の date コマンドと2番目の date コマンドでは、参照した環境変数 LANG の値が異なったためです。

taro@myhostname:~$ LANG=en_US date ; date
Fri Jun 14 17:13:49 JST 2024
2024年  6月 14日 金曜日 17:13:49 JST
taro@myhostname:~$

このように、代入式の後ろにコマンドを記述することで、その命令だけで有効になる値を代入することができます。

XDGユーザディレクトリの英語表記への変更で使っていた

上で解説した "変数への一時的な代入" は過去の記事で登場していました。 XDGユーザディレクトリを日本語表記から英語表記へ変更するために実行した、

LANG=C xdg-user-dirs-gtk-update

というコマンドです。 環境変数 LANG に一時的に "C" を代入しています。 "C" は標準言語を表し、わかりやすく言うと "翻訳しない" という意味になります。

  

まとめ

変数と呼ばれる箱のようなものがあります。 変数には、値を格納することも、参照することも、入れ替えることも、削除することもできます。

変数に値を代入するには、

NAME=value

と実行します。 これにより、変数 NAME に "value" が代入されます。 変数 NAME が存在していれば中身が上書きされ、存在していなければ新たに作成されます。

実行する命令の中だけで有効な値を代入するには、

NAME=value command

と実行します。 この命令が終了すると、変数 NAME の値は元に戻ります。

なお、変数名に使える文字は、

  1. 英字(大文字)
  2. 英字(小文字)
  3. 数字
  4. _(アンダーバー)

の4種類です。 ただし、変数名の先頭に数字を指定することはできません。

作成した変数は、

$NAME

または、

${NAME}

と記述して参照することができます。

変数が不要になったら、

unset NAME

で削除することができます。

操作/コマンド 説明
NAME=value 変数 NAME に "value" を代入する
$NAME 変数 NAME の中身を参照する
${NAME} 変数 NAME の中身を参照する
unset NAME 変数 NAME を削除する

変数には、シェル変数と環境変数があります。 シェル変数とはシェル内でしか参照できない変数のことで、シェルから呼び出した各種コマンドには渡されません。

一方、シェルから呼び出した各種コマンドからも参照できる変数が環境変数です。

変数を作成すると初期状態でシェル変数になります。 シェル変数に環境属性を付与することで環境変数に変化させることができます。 環境属性を取り除くとシェル変数に戻ります。

操作/コマンド 説明
export NAME シェル変数 NAME に環境属性を付与して環境変数に変える
export -n NAME 環境変数 NAME から環境属性を取り除いてシェル変数に戻す

ただし、

export NAME=value

と実行することで、変数を作成しつつ即座に環境変数にすることができます。

操作/コマンド 説明
export NAME=value シェル変数 NAME に "value" を代入し環境属性を付与して環境変数にする

なお、慣習としてシェル変数は小文字で、環境変数は大文字で表記するのが一般的です。

変数の一覧は set コマンドや printenv コマンドで確認することができます。 set コマンドではシェル変数と環境変数の両方が、printenv コマンドでは環境変数のみが表示されます。

操作/コマンド 説明
set シェル変数と環境変数の一覧を表示する
※シェル関数も表示されてしまう
(set -o posix; set) シェル変数と環境変数の一覧を表示する
※シェル関数は表示されない
printenv 環境変数のみの一覧を表示する

シェル変数のみの一覧を表示するコマンドはありません。 各種コマンドやシェルの機能を組み合わせ、

comm -23 <((set -o posix; set) | sort) <(printenv | sort)

と実行するしかありません。 これで、シェル変数のみの一覧が表示されます。

なお、あらかじめ用途が決められている変数を "システム変数" といい、以下のようなものがあります。

システム変数 説明
HOME ホームディレクトリのディレクトリパスが格納される
PATH シェルが各種アプリケーションやコマンドを探すディレクトリを :(コロン) で区切って設定する
PS1 シェルプロンプトの表示内容を設定する
LANG メッセージやメニュー項目・ボタンなどの表示言語を設定する
メニュー