HOWTO · Bash

Bash を使用してファイル拡張子を削除する

Bashでファイル名文字列の末尾の拡張子を取り除く方法、既知の接尾辞に対する`basename`の使い方、区切りテキストから`cut`でフィールドを抽出する方法を説明します。

このページの内容

Bashでファイル名の文字列から最後の拡張子を取り除くには、パラメーター展開を使います: name="${file%.*}"。パターン%.*は末尾から、ドットとその後の任意の文字列に一致する最短部分を取り除くため、それより前のドットは残ります。これは文字列を変換するだけで、ディスク上のファイル名は変更しません。

次の例を実行します:

このセクションのコードと表示されるラベルや出力は英語のままです。

file='annual.report.html'
name="${file%.*}"
printf '%s\n' "$name"

Bashのパラメーター展開で拡張子を取り除く

ファイル名がすでにBash変数に入っている場合、通常はパラメーター展開が最も簡単です。外部コマンドやパイプは必要ありません。元の値を残すには結果を別の変数に代入し、元の値が不要なら同じ変数に代入します。変数展開は引用符で囲み、空白やワイルドカード文字がファイル名の文字列の一部として扱われるようにします。

このパターンは最後のドットと、その後のすべての文字を取り除きます。たとえば、annual.report.htmlに適用するとannual.reportになり、notesには一致するドットがないため、そのままです。.profileのように先頭がドットの名前に使うと空文字列になるため、対象データに含まれる場合は別途扱ってください。この規則は文字列に基づくもので、接尾辞が実際のファイル形式を表すかどうかは判定しません。

拡張子が決まっている場合はbasenameを使う

取り除く接尾辞が正確に分かっている場合は、basenameを使います。2番目の引数で指定した接尾辞は、名前の末尾と一致する場合にだけ取り除かれます。たとえば、basename "$file" .htmlはannual.report.htmlをannual.reportに変換します。名前の末尾が.HTMLなど別の接尾辞なら、.htmlとは一致しないため残ります。変数を引用符で囲むことで、入力に含まれる空白も保護できます。

basenameは外部コマンドなので、Bash変数にすでに入っている値を処理する場合は、パラメーター展開のほうが直接的です。接尾辞が一致するときだけ取り除く動作が目的に合う場合に便利です。どちらの方法もディスク上のファイルは変更しません。

区切りテキストにはcutを使う(一般的なファイル名の接尾辞の除去には使わない)

cutコマンドは、区切り文字で分けられたテキストからフィールドを選ぶためのものです。cut -d '.' -f 1では各入力行をドットで分割し、最初のフィールドだけを残します。「最初のドットより前のテキストを残す」という規則でリストを処理する場合に使えます。最後のファイル名拡張子を取り除く汎用的な方法ではありません。たとえばannual.report.htmlに使うとannualになり、.reportと.htmlの両方が失われます。

改行区切りのリストを処理するには、たとえば次のようにテキストをcutへパイプします: printf '%s\n' "$file" | cut -d '.' -f 1。入力が複数のファイル名なら、printf '%s\n'が各ファイル名を1行ずつ出力します。オプション-dは区切り文字を指定し、-f 1は最初のフィールドを選びます。入力が区切り文字で構成され、そのフィールド選択が意図に合う場合にcutを使ってください。最後の接尾辞を取り除くには、代わりにBashのパラメーター展開を使います。

ドットを複数含むファイル名で違いを確認し、方法を選ぶ

ドットを複数含むファイル名を使うと、各方法の違いが分かります。${file%.*}をarchive.part.tar.gzに適用すると、.gzだけが取り除かれ、archive.part.tarが残ります。.gzが既知の接尾辞なら、basename "$file" .gzでも同じ結果になります。一方、cut -d '.' -f 1が残すのはarchiveだけです。最後の接尾辞を取り除くにはパラメーター展開、既知の接尾辞にはbasename、区切りテキストのフィールド選択にはcutを選びます。これらの例はファイル名の文字列を変換するもので、ファイルシステム上の名前を変更するには別の操作が必要です。