158

I'm looking for a small function that allows me to remove the extension from a filename.

I've found many examples by googling, but they are bad, because they just remove part of the string with "." . They use dot for limiter and just cut string.

Look at these scripts,

$from = preg_replace('/\.[^.]+$/','',$from);

or

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

When we add the string like this:

This.is example of somestring

It will return only "This"...

The extension can have 3 or 4 characters, so we have to check if dot is on 4 or 5 position, and then remove it.

How can it be done?

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
marc
  • 2,963
  • 7
  • 24
  • 25
  • 1
    What is a "real" extension ? You want to remove the last 4 or les chars if they are preceeded by a dot? – clyfe Mar 07 '10 at 10:18
  • "Col. Shrapnel" - it's designed for Windows users. "clyfe" - yes, i want remove everything after dot, but only if it's on 4 or 5 position, what will represent ".jpeg" or ".mp3". I just wan't remove it. I know i can do it manually using str-pos and cut string using using if statement (if 5 pos = dot then cut (rtrim) from right 5 chars, if 4 pos = dot then rtrim 4, else return without any modification. But maybe it's faster solution. – marc Mar 07 '10 at 10:30
  • 4
    What about .package files? Or .unity? Seems a bit arbitrary to restrict an extension to 4 characters. – rdb Sep 16 '16 at 00:03
  • If marc comes back, I hope he changes the accepted answer. – HoldOffHunger Jan 07 '22 at 02:24

18 Answers18

364

http://php.net/manual/en/function.pathinfo.php

pathinfo — Returns information about a file path

$filename = pathinfo('filename.md.txt', PATHINFO_FILENAME); // returns 'filename.md'
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
187

Try this one:

$withoutExt = preg_replace('/\.\w+$/', '', $filename);

So, this matches a dot followed by word characters ([a-zA-Z0-9_]) which are not a dot or a space.

Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
nickf
  • 537,072
  • 198
  • 649
  • 721
86

From the manual, 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
?>

It doesn't have to be a complete path to operate properly. It will just as happily parse file.jpg as /path/to/my/file.jpg.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Erik
  • 20,526
  • 8
  • 45
  • 76
  • I already checked this. Same mistake as above. Try access "$path_parts['filename']" from T.sec - "xxx" 23 12 32 3 a twym2 It will return only T. From above example it shouldn't remove anything ! – marc Mar 07 '10 at 10:26
61

Use PHP basename()

(PHP 4, PHP 5)

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

Outputs: string(4) "test"

Yasen
  • 3,400
  • 1
  • 27
  • 22
  • 2
    +1 If the mentioned requirements for an extension weren't strict, this would be the perfect answer. – Kayla Mar 18 '14 at 21:24
  • 1
    Looking at the commits on [php.net](http://php.net/manual/en/function.basename.php#85597) there is an idea about working with an array...which I think could be improved using something such as [array-walk](http://php.net/manual/en/function.array-walk.php) – CrandellWS Feb 03 '15 at 16:10
40

This is a rather easy solution and will work no matter how long the extension or how many dots or other characters are in the string.

$filename = "abc.def.jpg";

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

//$newFileName will now be abc.def

Basically this just looks for the last occurrence of . and then uses substring to retrieve all the characters up to that point.

It's similar to one of your googled examples but simpler, faster and easier than regular expressions and the other examples. Well imo anyway. Hope it helps someone.

wprenison
  • 544
  • 4
  • 11
15

Recommend use: pathinfo with PATHINFO_FILENAME

$filename = 'abc_123_filename.html';
$without_extension = pathinfo($filename, PATHINFO_FILENAME);
Alex
  • 3,646
  • 1
  • 28
  • 25
12

You could use what PHP has built in to assist...

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

Though if you are only dealing with a filename (.somefile.jpg), you will get...

./somefile

See it on CodePad.org

Or use a regex...

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

See it on CodePad.org

If you don't have a path, but just a filename, this will work and be much terser...

$withoutExt = pathinfo($path, PATHINFO_FILENAME);

See it on CodePad.org

Of course, these both just look for the last period (.).

alex
  • 479,566
  • 201
  • 878
  • 984
9

The following code works well for me, and it's pretty short. It just breaks the file up into an array delimited by dots, deletes the last element (which is hypothetically the extension), and reforms the array with the dots again.

$filebroken = explode( '.', $filename);
$extension = array_pop($filebroken);
$fileTypeless = implode('.', $filebroken);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Emanegux
  • 1,092
  • 2
  • 20
  • 38
5

I found many examples on the Google but there are bad because just remove part of string with "."

Actually that is absolutely the correct thing to do. Go ahead and use that.

The file extension is everything after the last dot, and there is no requirement for a file extension to be any particular number of characters. Even talking only about Windows, it already comes with file extensions that don't fit 3-4 characters, such as eg. .manifest.

bobince
  • 528,062
  • 107
  • 651
  • 834
4

There are a few ways to do it, but i think one of the quicker ways is the following

// $filename has the file name you have under the picture
$temp = explode( '.', $filename );
$ext = array_pop( $temp );
$name = implode( '.', $temp );

Another solution is this. I havent tested it, but it looks like it should work for multiple periods in a filename

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

Also:

$info = pathinfo( $filename );
$name = $info['filename'];
$ext  = $info['extension'];

// Or in PHP 5.4, i believe this should work
$name = pathinfo( $filename )[ 'filename' ];

In all of these, $name contains the filename without the extension

Ascherer
  • 8,223
  • 3
  • 42
  • 60
4
$image_name = "this-is.file.name.jpg";
$last_dot_index = strrpos($image_name, ".");
$without_extention = substr($image_name, 0, $last_dot_index);

Output:

this-is.file.name
Abhishek
  • 968
  • 10
  • 16
2

As others mention, the idea of limiting extension to a certain number of characters is invalid. Going with the idea of array_pop, thinking of a delimited string as an array, this function has been useful to me...

function string_pop($string, $delimiter){
    $a = explode($delimiter, $string);
    array_pop($a);
    return implode($delimiter, $a);
}

Usage:

$filename = "pic.of.my.house.jpeg";
$name = string_pop($filename, '.');
echo $name;

Outputs:

pic.of.my.house  (note it leaves valid, non-extension "." characters alone)

In action:

http://sandbox.onlinephpfunctions.com/code/5d12a96ea548f696bd097e2986b22de7628314a0

jbobbins
  • 1,221
  • 3
  • 15
  • 28
2

This works when there is multiple parts to an extension and is both short and efficient:

function removeExt($path)
{
    $basename = basename($path);
    return strpos($basename, '.') === false ? $path : substr($path, 0, - strlen($basename) + strlen(explode('.', $basename)[0]));
}

echo removeExt('https://example.com/file.php');
// https://example.com/file
echo removeExt('https://example.com/file.tar.gz');
// https://example.com/file
echo removeExt('file.tar.gz');
// file
echo removeExt('file');
// file
Dan Bray
  • 7,242
  • 3
  • 52
  • 70
1

You can set the length of the regular expression pattern by using the {x,y} operator. {3,4} would match if the preceeding pattern occurs 3 or 4 times.

But I don't think you really need it. What will you do with a file named "This.is"?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
1

Landed on this page for looking for the fastest way to remove the extension from a number file names from a glob() result.

So I did some very rudimentary benchmark tests and found this was the quickest method. It was less than half the time of preg_replace():

$result = substr($fileName,0,-4);

Now I know that all of the files in my glob() have a .zip extension, so I could do this.

If the file extension is unknown with an unknown length, the following method will work and is still about 20% faster that preg_replace(). That is, so long as there is an extension.

$result = substr($fileName,0,strrpos($fileName,'.'));

The basic benchmark test code and the results:

$start = microtime(true);

$loop = 10000000;
$fileName = 'a.LONG-filename_forTest.zip';
$result;

// 1.82sec preg_replace() unknown ext
//do {
//    $result = preg_replace('/\\.[^.\\s]{3,4}$/','',$fileName);
//} while(--$loop);

// 1.7sec preg_replace() known ext
//do {
//    $result = preg_replace('/.zip$/','',$fileName);
//} while(--$loop);

// 4.57sec! - pathinfo
//do {
//    $result = pathinfo($fileName,PATHINFO_FILENAME);
//} while(--$loop);

// 2.43sec explode and implode
//do {
//    $result = implode('.',explode('.',$fileName,-1));
//} while(--$loop);

// 3.74sec basename, known ext
//do {
//    $result = basename($fileName,'.zip');
//} while(--$loop);

// 1.45sec strpos unknown ext
//do {
//    $result = substr($fileName,0,strrpos($fileName,'.'));
//} while(--$loop);

// 0.73sec strpos - known ext length
do {
    $result = substr($fileName,0,-4);
} while(--$loop);

var_dump($fileName);
var_dump($result);
echo 'Time:['.(microtime(true) - $start).']';

exit;
Tigger
  • 8,980
  • 5
  • 36
  • 40
0

Use this:

strstr('filename.ext','.',true);
//result filename
undur_gongor
  • 15,657
  • 5
  • 63
  • 75
  • This only works if the filename does not have a period already. PHP Docs mention the first occurrence of needle – relipse May 02 '14 at 20:56
0

Try to use this one. it will surely remove the file extension.

$filename = "image.jpg";
$e = explode(".", $filename);
foreach($e as $key=>$d)
{
if($d!=end($e)
{

$new_d[]=$d; 
}

 }
 echo implode("-",$new_t);  // result would be just the 'image'
0

EDIT: The smartest approach IMHO, it removes the last point and following text from a filename (aka the extension):

$name = basename($filename, '.' . end(explode('.', $filename)));

Cheers ;)

andcl
  • 3,342
  • 7
  • 33
  • 61
  • While it could work, `end()` isn't supposed to work with a function passed as parameter. It also produces a notice: _Only variables should be passed by reference_ – CodeBrauer Apr 26 '18 at 15:11