Linux / コマンド / basename - パスから最後の名前を抽出

basenameは、パス文字列からディレクトリ部分を削除し、最後のファイル名やディレクトリ名のみを出力するコマンドです。必要に応じてファイル名の末尾の接尾辞も削除できるため、シェルスクリプトでパスを表示用の名前に変換する際に便利です。

basenameは、ファイルを開いたり、パスの存在を確認するコマンドではありません。入力された文字列を加工するため、存在しないパスにも使用できます。

basenameコマンドとは?

パスの最後の構成要素のみが必要なときにbasenameを使用します。

basename /home/user/report.txt

出力は次の通りです。

report.txt

入力されたパスがファイルかディレクトリかは重要ではありません。最後のスラッシュが整理された後、最後の名前を返します。

基本的な文法と使い方

以下は GNU Coreutils の basename を基準とします。オプションと入力名は別々の引数として指定します。空の文字列に対しても GNU 版は空の名前を出力して成功するため、空でない入力が必要な処理では入力値も確認してください。

basename 名前 [接尾辞]
basename オプション 名前 ...

最も基本的な使用例は次の通りです。

basename /var/log/nginx/access.log
basename /home/user/Documents/
basename relative/path/file.txt

各結果はaccess.log、Documents、file.txtです。パスの末尾の不要なスラッシュは削除されますが、ルートパスのように特別な入力は別途処理されます。

接尾辞を削除する

2 番目の引数で接尾辞を指定する

名前の後に接尾辞を指定すると、最後の名前がその文字列で終わる場合に削除されます。

basename /data/archive.tar.gz .gz
basename /home/user/report.txt .txt

出力はそれぞれ archive.tar と report です。.tar.gz 全体を削除するには、削除する文字列全体を指定します。

basename /data/archive.tar.gz .tar.gz

-s で複数の名前から接尾辞を削除する

GNU basename の -s または --suffix は接尾辞をオプションとして指定します。このオプションを使用すると、複数の名前を一緒に処理する -a 動作も有効になります。

basename -s .jpg /images/a.jpg /backup/b.jpg
basename --suffix=.log /var/log/app.log /tmp/test.log

接尾辞が一致しない場合は、元の最後の名前をそのまま出力します。名前全体と接尾辞が同じ場合にも、名前全体を空にせず残します。たとえば basename name name の結果は name です。接尾辞は正規表現ではなく、文字通り比較する文字列です。

複数のパスを処理する

-aで複数の名前を出力する

-a または --multiple を使うと、複数のパスを一度に処理し、各結果を一行ずつ出力します。

basename -a /srv/www/index.html /var/log/syslog /home/user

出力は次のような形になります。

index.html
syslog
user

-zで結果をNUL(値が0の文字)区切りにする

ファイル名には改行文字が含まれることがあります。自動化であいまいさを避けるために、-z または --zero を使って各結果の末尾に改行の代わりに NUL 文字を出力できます。

basename -z -a /data/file1 /data/file2

NUL 区切り出力を受け取る次のコマンドも同じ形式をサポートする必要があります。画面で直接確認するためのオプションではなく、安全なプログラム間の受け渡しのための機能です。

basename と dirname の比較

入力 basename dirname
/home/user/report.txt report.txt /home/user
docs/manual.pdf manual.pdf docs
notes.txt notes.txt .
/ / /

basename と dirname によるディレクトリ部分の抽出は、パス文字列を補完的に分割するときに便利です。ただし、出力2つを単純にスラッシュで再接続すると、重複したスラッシュや特殊な入力のために元の文字列と正確に一致しないことがあります。

ファイル拡張子を処理する

知っている拡張子を削除する

削除する拡張子が決まっている場合は、接尾辞引数を使用する方法が明確です。

basename photo.webp .webp
basename backup.tar.gz .tar.gz

この方法は末尾が完全に一致する場合にのみ削除されるため、report.txt.bakから.txtは削除されません。

最後のドット以降を必ずしも拡張子と見なさない

ファイル名にドットがあるからといって、必ずしも拡張子があるわけではありません。.profileのようにドットで始まる隠しファイル、archive.tar.gzのように複数の接尾辞があるファイル、ドットで終わる名前もあります。

業務規則に従って削除する接尾辞を明確に定め、単に最後のドット以降をすべて削除する処理は慎重に使用してください。

シェルスクリプトでの活用方法

パスから表示用ファイル名を取得する

path='/srv/uploads/annual report.pdf'
name=$(basename -- "$path") || exit 1
printf 'ファイル名: %s\n' "$name"

このコードを Bash スクリプトとして保存して実行すると、ファイルが実在しなくても ファイル名: annual report.pdf と表示されます。コマンド置換は末尾の改行を取り除くため、改行で終わる名前までそのまま保つ用途では -z と NUL 対応の受け取り方法を検討してください。--は以降の文字列をオプションではなく名前として処理します。ハイフンで始まる入力を扱う際に便利で、変数は常にダブルクォートで囲むのが安全です。

POSIXシェルパラメータ展開と比較する

シェル内でパスの最後の部分だけが必要な場合、外部コマンドの代わりにパラメータ展開を使用することもできます。

path='/srv/uploads/report.pdf'
name=${path##*/}
printf '%s\n' "$name"

しかし、パスがスラッシュで終わる場合やルートパスの場合、basenameと結果が異なることがあります。入力形式を制御できない場合、独自に作成した文字列ルールとbasenameの動作が同じであると仮定しないでください。

主なオプションまとめ

オプション 説明
-a, --multiple 複数の名前を処理し、それぞれの結果を出力します。
-s 接尾辞, --suffix=接尾辞 各名前の末尾から指定した接尾辞を取り除き、複数の名前の処理も有効にします。
-z, --zero 各結果を改行ではなくNUL文字で終わらせます。
--help 使用方法とサポートオプションを出力します。
--version インストールされているGNU Coreutilsのバージョンを出力します。

-a、-s、-zのようなオプションはGNU拡張です。さまざまなUnix系で実行するスクリプトであれば、対象システムの実装を確認し、POSIXで規定された基本形式を優先してください。

よく発生する問題

ファイルがなくても結果が出力されます。

正常な動作です。basenameはファイルの存在を確認せずに入力文字列から最後の部分を抽出します。実際のファイルが必要な作業であれば、別途存在有無と権限のチェックを行う必要があります。

空白があるパスが複数の引数に分かれる。

変数を二重引用符で囲まないと、シェルの単語分割やglob展開が発生する可能性があります。

basename -- "$path"

接尾辞が削除されない

接尾辞は最後の名前の末尾と完全に一致している必要があります。大文字と小文字も区別され、正規表現やワイルドカードとして解釈されることはありません。

FAQ

basenameは実際のファイル名を変更しますか?

いいえ。入力したパス文字列から最後の名前を計算して出力するだけで、ファイルやディレクトリを変更することはありません。

basenameで拡張子を削除できますか?

basename パス .txtのように削除したい接尾辞を第二引数として指定できます。GNU環境で複数の名前を処理するにはbasename -s .txt 名前...を使用できます。

basenameは存在しないパスでも動作しますか?

はい。パス文字列のみを処理するため、実際にファイルがなくても最後の構成要素を出力します。

dirnameと何が違いますか?

basenameは最後の名前を出力し、dirnameは最後の名前を除いたディレクトリ部分を出力します。

参考資料