「拡張子除去」で何をしたいのかイメージする
まず、ゴールをはっきりさせます。
"/var/www/html/report/sales.csv" → "/var/www/html/report/sales"
"/var/www/html/image/photo.jpeg" → "/var/www/html/image/photo"
"archive.tar.gz" → "archive.tar"
"README" → "README"(拡張子なしなのでそのまま)
"https://example.com/files/doc.pdf" → "https://example.com/files/doc"
やりたいことはこうです。
ファイルパスや URL から「拡張子だけを取り除いた文字列」を取り出したい。
業務だと、ファイル名から「拡張子を除いたベース名」を使って別名を作る、
拡張子を変えて派生ファイルを作る(report.csv → report.log など)、
URL のパスから「拡張子なしのルーティングキー」を取りたい、などでよく使います。
ここを自前で「最後の . より左を取る」みたいに書き始めると、
複数ドット、拡張子なし、URL などで簡単に壊れます。
PHP には、これを安全にやってくれる関数がすでにあります。
基本の主役:pathinfo の filename を使う
pathinfo の「filename」と「extension」
前回の「拡張子取得」と同じく、ここでも pathinfo が主役です。
$info = pathinfo('/var/www/html/report/sales.csv');
var_dump($info);
PHP結果はこうでした。
array(4) {
["dirname"] => "/var/www/html/report"
["basename"] => "sales.csv"
["extension"] => "csv"
["filename"] => "sales"
}
PHPここで注目したいのが filename です。
「拡張子を除いたファイル名部分」
がすでに取れている、ということです。
つまり、
$filename = pathinfo('/var/www/html/report/sales.csv', PATHINFO_FILENAME);
echo $filename; // sales
PHPこれが「拡張子除去」の基本になります。
ファイルパスから「拡張子を除いたパス」を作る
ディレクトリ込みで「拡張子だけ除去」したい
多くの場合、「ファイル名だけ」ではなく「パス全体から拡張子だけを取りたい」ことが多いです。
"/var/www/html/report/sales.csv"
→ "/var/www/html/report/sales"
これを安全にやるには、
dirnameとfilenameをpathinfoで取る- それを
/でつなぎ直す
という形にするとスッキリします。
/**
* ファイルパスから「拡張子を除いたパス」を取得する
* 例: /path/to/file.csv → /path/to/file
*/
function stripExtensionFromPath(string $path): string
{
$info = pathinfo($path);
$dir = $info['dirname'] ?? '';
$name = $info['filename'] ?? '';
if ($dir === '' || $dir === '.' || $dir === DIRECTORY_SEPARATOR) {
// ディレクトリ情報がない(カレントディレクトリ扱い)場合は、ファイル名だけ返す
return $name;
}
return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
}
PHP使い方の例です。
echo stripExtensionFromPath('/var/www/html/report/sales.csv');
// /var/www/html/report/sales
echo stripExtensionFromPath('sales.csv');
// sales
echo stripExtensionFromPath('README');
// README(拡張子がないのでそのまま)
PHPここでのポイントは、「拡張子がない場合も安全に動く」ことです。pathinfo の filename は、拡張子がなくても「そのままの名前」を返してくれます。
URL から「拡張子を除いた URL」を作る
URL 全体をそのまま pathinfo に渡すのは危ない
URL をそのまま pathinfo に渡すと、
クエリやフラグメントまで含めて「パス」として扱われてしまうことがあります。
$info = pathinfo('https://example.com/files/doc.pdf?download=1');
var_dump($info['filename']); // doc.pdf?download=1 みたいな変な結果になる可能性
PHPなので、URL の場合は必ず
parse_urlで「パス部分」だけを取り出す- そのパスに対して
pathinfoを使う - 最後に URL 全体を組み立て直す
という流れにします。
パス部分の拡張子だけを除去した URL を作る
/**
* URL の「パス部分の拡張子」だけを除去した URL を返す
* 例: https://example.com/files/doc.pdf?x=1
* → https://example.com/files/doc?x=1
*/
function stripExtensionFromUrl(string $url): string
{
$parts = parse_url($url);
if ($parts === false) {
// URL として解釈できない場合は、そのまま返すか、空文字にするかは設計次第
return $url;
}
$scheme = $parts['scheme'] ?? null;
$host = $parts['host'] ?? null;
$port = $parts['port'] ?? null;
$path = $parts['path'] ?? '';
$query = $parts['query'] ?? null;
$fragment = $parts['fragment'] ?? null;
$user = $parts['user'] ?? null;
$pass = $parts['pass'] ?? null;
// パスから拡張子を除去
if ($path !== '') {
$info = pathinfo($path);
$dir = $info['dirname'] ?? '';
$name = $info['filename'] ?? '';
if ($dir === '' || $dir === '/' || $dir === '.') {
$path = '/' . $name;
} else {
$path = rtrim($dir, '/') . '/' . $name;
}
}
// URL を再構築
$result = '';
if ($scheme !== null) {
$result .= $scheme . '://';
}
if ($user !== null) {
$result .= $user;
if ($pass !== null) {
$result .= ':' . $pass;
}
$result .= '@';
}
if ($host !== null) {
$result .= $host;
}
if ($port !== null) {
$result .= ':' . $port;
}
$result .= $path;
if ($query !== null && $query !== '') {
$result .= '?' . $query;
}
if ($fragment !== null && $fragment !== '') {
$result .= '#' . $fragment;
}
return $result;
}
PHP使い方の例です。
echo stripExtensionFromUrl('https://example.com/files/doc.pdf');
// https://example.com/files/doc
echo stripExtensionFromUrl('https://example.com/files/doc.pdf?download=1');
// https://example.com/files/doc?download=1
echo stripExtensionFromUrl('https://example.com/files/');
// https://example.com/files (拡張子がないのでそのまま)
echo stripExtensionFromUrl('https://example.com');
// https://example.com
PHPここでの重要ポイントは、「クエリやフラグメントはそのまま残す」ことです。
あくまで「パスの最後の要素の拡張子だけ」を削っています。
「複数ドット」のファイル名をどう扱うか
archive.tar.gz → archive.tar にするのが基本
pathinfo の filename は、「最後のドットより左」を返します。
$info = pathinfo('archive.tar.gz');
echo $info['filename']; // archive.tar
echo $info['extension']; // gz
PHPつまり、「拡張子除去」を filename ベースでやると、
"archive.tar.gz" → "archive.tar"
になります。
実務では、これで十分なことが多いです。
- 「
.gzを外して、.zipに変えたい」 - 「
.gzを外して、ログファイル名にしたい」
など、「最後の拡張子だけを意識したい」ケースが多いからです。
もし、「.tar.gz まで含めて一気に外したい」などの要件があるなら、
前回の「複合拡張子」の話のように、別途ルールを決めて処理する必要があります。
実務での使いどころのイメージ
拡張子だけ変えて派生ファイル名を作る
例えば、CSV ファイルからログファイル名を作りたいケース。
$csvPath = '/var/www/html/report/sales_2025.csv';
$base = stripExtensionFromPath($csvPath);
$logPath = $base . '.log';
echo $logPath;
// /var/www/html/report/sales_2025.log
PHP「拡張子だけ変えたい」という処理は、
業務バッチやレポート生成でよく出てきます。
URL から「ルーティングキー」を取りたい
例えば、こんな URL をルーティングに使っているとします。
/entry/123.html
/entry/456.html
ここから「123」「456」だけ取りたい。
$url = '/entry/123.html';
$path = 'https://dummy' . $url; // parse_url 用のダミー
$noExtUrl = stripExtensionFromUrl($path);
// https://dummy/entry/123
$noExtPath = parse_url($noExtUrl, PHP_URL_PATH);
// /entry/123
$id = basename($noExtPath);
// 123
PHP少しステップは多いですが、「拡張子を気にせず ID を取りたい」ときに、
こういう組み合わせ方もできます。
まとめ:今日からの「拡張子除去」ユーティリティ
大事なところだけ、ぎゅっとまとめます。
拡張子除去は、pathinfo($path, PATHINFO_FILENAME) を使うのが基本。
パス全体から拡張子だけを除去したいときは、「dirname+filename をつなぎ直す」。
URL の場合は、parse_url でパス部分だけを取り出してから pathinfo を使い、最後に URL を再構築する。
複数ドットのファイル名は、「最後の拡張子だけを外す(archive.tar.gz → archive.tar)」のが現実的な落としどころ。
核になるコードは、この2つです。
function stripExtensionFromPath(string $path): string
{
$info = pathinfo($path);
$dir = $info['dirname'] ?? '';
$name = $info['filename'] ?? '';
if ($dir === '' || $dir === '.' || $dir === DIRECTORY_SEPARATOR) {
return $name;
}
return rtrim($dir, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $name;
}
function stripExtensionFromUrl(string $url): string
{
$parts = parse_url($url);
if ($parts === false) {
return $url;
}
$path = $parts['path'] ?? '';
if ($path !== '') {
$info = pathinfo($path);
$dir = $info['dirname'] ?? '';
$name = $info['filename'] ?? '';
if ($dir === '' || $dir === '/' || $dir === '.') {
$path = '/' . $name;
} else {
$path = rtrim($dir, '/') . '/' . $name;
}
}
$scheme = $parts['scheme'] ?? null;
$host = $parts['host'] ?? null;
$port = $parts['port'] ?? null;
$query = $parts['query'] ?? null;
$fragment = $parts['fragment'] ?? null;
$user = $parts['user'] ?? null;
$pass = $parts['pass'] ?? null;
$result = '';
if ($scheme !== null) {
$result .= $scheme . '://';
}
if ($user !== null) {
$result .= $user;
if ($pass !== null) {
$result .= ':' . $pass;
}
$result .= '@';
}
if ($host !== null) {
$result .= $host;
}
if ($port !== null) {
$result .= ':' . $port;
}
$result .= $path;
if ($query !== null && $query !== '') {
$result .= '?' . $query;
}
if ($fragment !== null && $fragment !== '') {
$result .= '#' . $fragment;
}
return $result;
}
PHPもし、あなたのコードの中で「substr と strrpos('.') で拡張子を削っているところ」があれば、そこがこのユーティリティの差し替えポイントです。
