関数の定義|bashシェルでfunctionを使った定義・引数・戻り値・.bashrc永続化の実務手順

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)【Linux入門】初心者のための基礎知識・講座 > 関数の定義|bashシェルでfunctionを使った定義・引数・戻り値・.bashrc永続化の実務手順

この記事のポイント

・bashの関数は function 名前() { 処理; } で定義する
・関数を定義したシェル内でだけ利用でき、別ターミナルには引き継がれない
・declare -f で定義済み関数一覧、unset で関数を削除できる
・.bashrc に書けば常用関数として永続化できる

bashで「同じコマンドの組み合わせを毎回打つのが面倒」「短い操作だけど引数の処理を入れたい」と感じたことはありませんか。
そんなときに役立つのが 関数(function) の定義です。

この記事では、bashで 関数を定義する 基本書式から、引数の受け取り方、定義済み関数の確認・削除、.bashrc への永続化まで、現場でそのまま使える形で解説します。
シェルスクリプトを書き始めたばかりの方でも、読み終えたあとに自分専用の関数をすぐに作れるレベルを目指します。

「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

なぜbashで関数を定義するのか(背景・原理)

bashの関数は、よく使うコマンドの組み合わせに名前を付けて、ひとつのコマンドのように再利用できる仕組みです。
エイリアスでは「コマンドの別名」しか作れませんが、関数なら引数を受け取って処理を分岐させたり、複数行のコマンドをまとめたりできます。

たとえば「特定ディレクトリのシンボリックリンクだけ一覧表示する」「ログから当日分だけ抜き出す」といった日常作業は、関数化することで一発呼び出しが可能になります。

セミナーの受講生にも「ターミナルで同じ操作を3回以上繰り返したら関数化を考える」というルールを伝えています。タイピング量だけでなく、ミスの確率も大幅に減るからです。

関数を定義する基本書式(function構文)

bashで関数を定義する書式は次の2通りで、どちらも有効です。

function 関数名() { コマンド; }
関数名() { コマンド; }

「{」の直後と「}」の直前には半角スペースが必要で、コマンドの末尾にはセミコロン「;」を付けます。
ここを省略すると「syntax error near unexpected token」のエラーが出るので注意してください。

下記の例では、指定したディレクトリのシンボリックリンクファイルのみをリスト表示する関数 lslink を定義しています。

$ function lslink() { ls -l $1 | grep '^l'; } $ lslink /etc lrwxrwxrwx. 1 root root 11 1月 14 14:22 2014 init.d -> rc.d/init.d lrwxrwxrwx. 1 root root 7 1月 14 14:25 2014 rc -> rc.d/rc lrwxrwxrwx. 1 root root 13 1月 14 14:25 2014 rc.local -> rc.d/rc.local lrwxrwxrwx. 1 root root 10 1月 14 14:25 2014 rc0.d -> rc.d/rc0.d lrwxrwxrwx. 1 root root 10 1月 14 14:25 2014 rc1.d -> rc.d/rc1.d lrwxrwxrwx. 1 root root 10 1月 14 14:25 2014 rc2.d -> rc.d/rc2.d

関数を実行するには、通常のコマンドと同じく関数名を入力します。
関数を利用できるのはその関数を定義したシェル内のみで、別のターミナルを開いても引き継がれません。永続化したい場合は後述する「.bashrcに登録する」を参照してください。

関数の引数($1 $2 $@)を受け取って処理する

bashの関数は、シェルスクリプトと同じく位置パラメータで引数を受け取ります。

$1, $2, $3 ... :1番目、2番目、3番目の引数
$@ :すべての引数を個別にまとめて参照
$# :引数の個数
$0 :シェル名(関数では関数名ではないことに注意)

たとえば、引数で渡したファイルの行数だけを表示する関数は次のように書けます。

$ function lc() { wc -l "$1" | awk '{print $1}'; } $ lc /etc/passwd 45

引数を二重引用符で囲む("$1")のがポイントです。スペースを含むファイル名でも安全に渡せます。

関数の戻り値とreturnの使い方

bash関数からの戻り値は、return 文で0~255の整数を返すか、関数の最後に実行されたコマンドの終了ステータスを返します。

「文字列を戻り値にしたい」というケースは、echo の出力をコマンド置換でキャプチャするのが定石です。

$ function add() { echo $(($1 + $2)); } $ result=$(add 3 5) $ echo $result 8

return は終了ステータスを返すだけなので、return 8 と書いても $? に8が入るだけで $result には文字列として入りません。
ここを混同するとシェルスクリプト初心者が必ずつまずきます。

関数の確認と削除(declare -f / unset)

現在定義されている関数の一覧と中身を確認したい場合は、declare -f コマンドを使います。

$ declare -f lslink () { ls --color=auto -l $1 | grep '^l' }

上記の結果は表示内容を省略して lslink の部分のみを抜粋しています。
関数名だけを一覧したい場合は declare -F(大文字F)を使うと、関数名一覧のみが表示されます。

特定の関数の定義内容を確認するなら、関数名を指定します。

$ declare -f lslink lslink () { ls -l $1 | grep '^l' }

setコマンドを使用すると、定義されている関数が変数リストに続いて一覧表示されます。ただし変数も大量に表示されるため、関数だけ確認したい場合は declare -f を使うほうが実用的です。

bashでは変数名と関数名を区別しないため、名前が重複しないよう注意する必要があります。同じ名前で変数を定義すると関数が呼び出せなくなるケースもあります。

関数定義を削除するには、変数を削除するときと同様に unset コマンドを使用します。下記の例では、関数 lslink を削除しています。

$ unset lslink $ lslink /etc -bash: lslink: コマンドが見つかりません

変数と関数が同名の場合は、関数のみ削除する unset -f 関数名 を使うと安全です。

.bashrc に登録して関数を永続化する

シェルを閉じると関数の定義は消えてしまいます。次回ログイン以降も使い続けるには、ユーザーのホームディレクトリにある .bashrc に関数を追記します。

# ~/.bashrc に追記 function lslink() { ls -l "$1" | grep '^l' }

追記したあとは、新しいシェルを開くか、現在のシェルで以下を実行して反映します。

$ source ~/.bashrc

全ユーザーで共有したい場合は /etc/bashrc(CentOS/RHEL系)または /etc/bash.bashrc(Debian/Ubuntu系)に書く方法もありますが、誤って書くと全ユーザーのログインに影響が出ます。基本は個人の ~/.bashrc に書くのが安全です。

bash関数 早見表

やりたいこと コマンド
関数を定義する function 名前() { 処理; }
関数を定義する(function省略) 名前() { 処理; }
引数を受け取る $1 $2 $@ "$1"
関数の終了ステータスを返す return 0
関数の文字列を取得する result=$(関数名 引数)
定義済み関数と中身を一覧 declare -f
定義済み関数名のみ一覧 declare -F
特定の関数定義を表示 declare -f 関数名
関数を削除する unset -f 関数名
関数を永続化する ~/.bashrc に追記して source ~/.bashrc

「command not found」が出た時の対処法

関数を定義したつもりなのに「command not found」「コマンドが見つかりません」と出る場合、原因は次の3つが代表的です。

・別シェルで定義した:定義はシェルごとなので、ターミナルを開き直すと消える
・スクリプトの中で定義した:子プロセスで定義された関数は親シェルに引き継がれない(source か . で実行する)
・スペル違い・大文字小文字違い:bashは大文字小文字を厳密に区別する

スクリプトを source 経由で読み込めば、定義した関数がそのまま現在のシェルで使えるようになります。

$ source ./myfunc.sh # または $ . ./myfunc.sh

本記事のまとめ

bashの関数function 構文で定義することで、よく使うコマンドの組み合わせを短い名前で呼び出せます。
引数の受け取りや戻り値、declare -f での確認、unset での削除、.bashrc での永続化まで身につければ、日々のターミナル作業は確実に速くなります。

シェルスクリプトを書く前段階として、まずは普段の作業を関数化していくところから始めてみてください。
無料のLinux Master Magazineでは、現場で本当に使われているbashテクニックを定期的に配信しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。