Bashでprintfという名前がalias、function、builtin、実行ファイルのどれとして解釈され得るか確認する。
PATH上の実行ファイルだけでなく、同名の候補をすべて表示する。
適切なコマンドはどれか。
Bashのtypeは名前がコマンドとしてどう解釈されるかを示す。-aは同名の候補をすべて表示する。
詳細解説
which printf通常はPATH上の実行ファイル探索が中心でshell組み込み等の全解釈を示さない。
whichの出力から、現在のBashのaliasや関数、組み込みを含む全候補を列挙できたとは判断できない。実装依存の補助機能と、Bash自身への照会を区別する。
whereis printfbinaryやmanualの標準配置検索でshellのalias等を扱わない。
whereisは実行ファイルやマニュアル等の配置を探す。現在のBashに定義したaliasや関数を列挙するものではない。
type -p printf-pはfileと分類される場合のパス表示で、aliasや組み込みがあれば空になる場合がある。全候補の列挙や-Pの外部探索とは異なる。
小文字-pは、Bashが名前をfileと分類するときのパス表示である。検証ではaliasや関数があるため空になり、PATHに置いた外部printfの不存在を意味しない。大文字-Pとの違いを確認する。
type -a printfBashが認識する同名の全候補をalias、function、builtin、PATHを含めて表示する。
-aは現在のシェルにある定義も含めて候補を示す。検証ではalias、関数、組み込み、外部ファイルを意図的に共存させ、全候補・小文字-p・大文字-Pを比較する。
実際に確かめる
一時的な検証環境で実行できる例です。
LAB_DIR=$(mktemp -d) || exit 1
printf '#!/bin/sh\nexit 0\n' > "$LAB_DIR/printf"
chmod u+x "$LAB_DIR/printf" || exit 1
(
export LC_ALL=C
PATH="$LAB_DIR"
hash -r
printf() { :; }
shopt -s expand_aliases
alias printf='builtin printf'
LAB_ALL=$(type -a printf)
if [[ "$LAB_ALL" == *"aliased to"* && "$LAB_ALL" == *"is a function"* && "$LAB_ALL" == *"is a shell builtin"* && "$LAB_ALL" == *"$LAB_DIR/printf"* ]]; then
builtin printf 'all=alias+function+builtin+external\n'
fi
LAB_SMALL_P=$(type -p printf)
[[ -z "$LAB_SMALL_P" ]] && builtin printf 'type-p=empty\n'
LAB_BIG_P=$(type -P printf)
[[ "$LAB_BIG_P" == "$LAB_DIR/printf" ]] && builtin printf 'type-P=external\n'
)
rm -- "$LAB_DIR/printf"
rmdir -- "$LAB_DIR"参考にした公式資料
期待される結果
all=alias+function+builtin+external
type-p=empty
type-P=external理解のポイント
- shell builtin
- alias/functionも対象
- -aは全候補
確認時の注意
- 確認環境: Bash 5.2 / GNU coreutils。個人設定を読まない新規Bashでerrexit無効。比較用PATH・LC_ALL・hash・alias/関数は子シェル内だけに限定する。HOMEは変更しない。
- alias展開が通常無効の非対話Bashでも比較条件を再現できるよう、子シェル内だけでexpand_aliasesを有効にする。候補の外部printfは起動せず、出力はbuiltin printfで行う。
- type -aの本文には関数定義なども含まれるため、検証は4種類が現れたことを確認した固定マーカーを出す。-pの空出力と-Pの外部パスを別に検査する。
- 組み込みと外部ファイルだけの場合に、aliasと関数を加えると候補が増える。前提が異なる出力を比較し、常に4種類が存在するとは判断しない。
基礎のおさらい
-pの空出力と外部ファイルの有無
同名aliasや組み込みが選ばれると-pは空になり得る。空出力だけからPATH上にもファイルがないと判断せず、外部探索が目的なら-Pの結果と区別する。
全候補には現在の定義が反映される
aliasや関数は、定義されている場合に候補へ現れる。単に全候補と指定したことによって存在しない定義が作られるわけではない。
キャッシュとPATHの先頭を混同しない
-p/-Pにはhashに記憶された値が関係する場合がある。今回の比較はhash -rで初期化した子シェルを使い、常にPATHの先頭だけで説明できるという一般化を避ける。