如何从文件名中删除扩展名(仅限真实扩展名!)

158
我正在寻找一个小函数,可以让我从文件名中去除扩展名。
通过谷歌搜索,我找到了很多示例,但它们都不好,因为它们只是简单地删除带有"."的部分字符串。它们使用点作为分隔符,然后直接截取字符串。
看看这些脚本,
$from = preg_replace('/\.[^.]+$/','',$from);

或者

 $from=substr($from, 0, (strlen ($from)) - (strlen (strrchr($filename,'.'))));

当我们像这样添加字符串时:

This.is example of somestring

它只会返回 "This"...
扩展名可以有3或4个字符,所以我们必须检查点是否在第4或第5个位置,然后将其删除。
如何完成这个任务?

1
什么是“真正的”扩展名?如果它们前面有一个点,您想要删除最后4个或更少的字符吗? - clyfe
"Col. Shrapnel" - 它是为 Windows 用户设计的。"clyfe" - 是的,我想删除点号后面的所有内容,但仅当它在第四或第五个位置,代表“.jpeg”或“.mp3”。 我只是想将其删除。我知道可以使用 str-pos 和 cut string 手动执行此操作,使用 if 语句(如果第5个位置=点,则从右侧剪切(rtrim)5个字符;如果第4个位置=点,则 rtrim 4,否则返回不进行任何修改即可。 但也许有更快的解决方案。 - marc
4
“.package”文件怎么办?或者“.unity”呢?把扩展名限制在4个字符似乎有点武断。 - rdb
如果Marc回来了,我希望他能够更改被接受的答案。 - HoldOffHunger
18个回答

365

187
试试这个:
$withoutExt = preg_replace('/\.\w+$/', '', $filename);

所以,这个正则表达式匹配一个点后面跟着的不是点或空格的单词字符([a-zA-Z0-9_])。

3
问题在于,还有人会将文件重命名为类似于20120720.something.somethingelse.jpg的格式。 - Obmerk Kronen
4
我认为带有两个字符作为扩展名的文件无法使用。 - NaturalBornCamper
1
请注意,如果您不执行变量替换,则应使用单引号,例如 "$var" - aelgoa
2
为了支持2到4个字符的扩展名,您应该使用{2,4}而不是{3,4} - Timo Huovinen
它有很多赞,但我认为它并不总是给出正确的结果,可以看看之前的评论。文件名中可能会出现多个点。文件名可以有三个或四个字符以上或以下。 - Sarah Trees
显示剩余2条评论

86

根据手册,pathinfo

<?php
    $path_parts = pathinfo('/www/htdocs/index.html');

    echo $path_parts['dirname'], "\n";
    echo $path_parts['basename'], "\n";
    echo $path_parts['extension'], "\n";
    echo $path_parts['filename'], "\n"; // Since PHP 5.2.0
?>

它不必是完整的路径才能正常操作。它可以同样愉快地解析 file.jpg/path/to/my/file.jpg


我已经检查过了。与上面一样的错误。 尝试从T.sec - "xxx" 23 12 32 3 a twym2访问"$path_parts['filename']"它将仅返回T。从上面的例子中,它不应该删除任何内容! - marc

63

使用PHP basename()

(PHP 4, PHP 5)

var_dump(basename('test.php', '.php'));

输出: string(4) "test"


2
如果对于扩展的要求不是那么严格,那么这将是一个完美的答案。+1 - Kayla
1
php.net 的提交记录来看,有一个关于使用数组的想法...我认为可以使用 array-walk 等方法进行改进。 - CrandellWS

42

这是一个相当简单的解决方案,无论扩展名有多长或者字符串中有多少个点或其他字符,都可以使用该方法。

$filename = "abc.def.jpg";

$newFileName = substr($filename, 0 , (strrpos($filename, ".")));

//$newFileName will now be abc.def
基本上,这只是在寻找最后一个"."的出现位置,然后使用子字符串来检索到那一点之前的所有字符。 它类似于您搜索的示例之一,但比正则表达式和其他示例更简单、更快捷、更易于理解。 在我看来,至少是这样。希望它能对某人有所帮助。

3
我知道这来得太晚了,但我认为这是最好的答案。效果很好。 - Agbogidi Michael
3
这对于没有扩展名的 *nix 隐藏文件不起作用,例如 .htaccess 文件。 - Fr0zenFyr

17

推荐使用: pathinfo PATHINFO_FILENAME

$filename = 'abc_123_filename.html';
$without_extension = pathinfo($filename, PATHINFO_FILENAME);

1
这不是5年前在这个页面上说过的吗? - mickmackusa

12

你可以使用 PHP 内置的东西来帮助...

$withoutExt = pathinfo($path, PATHINFO_DIRNAME) . '/' . pathinfo($path, PATHINFO_FILENAME);

如果你只处理一个文件名(.somefile.jpg),那么你将会得到...

./somefile

在CodePad.org上查看

或者使用正则表达式...

$withoutExt = preg_replace('/\.' . preg_quote(pathinfo($path, PATHINFO_EXTENSION), '/') . '$/', '', $path);

在 CodePad.org 上查看

如果你只有一个文件名而没有路径,这个方法可以帮助你解决问题并且更加简洁...

$withoutExt = pathinfo($path, PATHINFO_FILENAME);

在CodePad.org上查看

当然,这两种方法都只是寻找最后一个句点 (.)。


正如解决方案的最后一行所提到的那样,对于像.htaccess这样的文件名,它将失败。 - Fr0zenFyr

9
以下代码对我来说很有效,而且非常简短。它只是将文件拆分成由点分隔的数组,删除最后一个元素(理论上是扩展名),然后再次用点重新格式化数组。
$filebroken = explode( '.', $filename);
$extension = array_pop($filebroken);
$fileTypeless = implode('.', $filebroken);

如果文件没有扩展名,则返回false;如果文件是.htaccess,则返回空。 - Timo Huovinen

5

我在谷歌上找到了很多例子,但它们不好,因为只是用“.”删除一部分字符串。

实际上,那绝对是正确的做法。请放心使用。

文件扩展名是最后一个点之后的所有内容,而且没有任何要求文件扩展名必须是特定数量的字符。即使仅谈论Windows,它已经带有不符合3-4个字符的文件扩展名,例如.manifest


2
不要忘记在Apache环境中使用的.htaccess.htpasswd - h2ooooooo

4
$image_name = "this-is.file.name.jpg";
$last_dot_index = strrpos($image_name, ".");
$without_extention = substr($image_name, 0, $last_dot_index);

输出结果:

this-is.file.name

1
$the_extension = substr($image_name, $last_dot_index, $last_dot_index);将此添加以获取文件的扩展名。 - I_ATE_YOUR_WORK_FILES

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接