pathinfo

(PHP 4 >= 4.0.3, PHP 5, PHP 7, PHP 8)

pathinfo返回文件路径的信息

说明

pathinfo ( string $path , int $options = PATHINFO_DIRNAME | PATHINFO_BASENAME | PATHINFO_EXTENSION | PATHINFO_FILENAME ) : mixed

pathinfo() 返回一个关联数组包含有 path 的信息。返回关联数组还是字符串取决于 options

参数

path

要解析的路径。

options

如果指定了,将会返回指定元素;它们包括:PATHINFO_DIRNAMEPATHINFO_BASENAMEPATHINFO_EXTENSIONPATHINFO_FILENAME

如果没有指定 options 默认是返回全部的单元。

返回值

如果没有传入 options ,将会返回包括以下单元的数组 arraydirnamebasenameextension(如果有),以 及filename

Note:

If the path does not have an extension, no extension element will be returned(以下第二个案例)。

If options is present, returns a string containing the requested element.

更新日志

版本 说明
5.2.0 添加了常量 PATHINFO_FILENAME

范例

Example #1 pathinfo() 例子

<?php
$path_parts 
pathinfo('/www/htdocs/inc/lib.inc.php');

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
?>

以上例程会输出:

/www/htdocs/inc
lib.inc.php
php
lib.inc

Example #2 pathinfo() example showing difference between null and no extension

<?php
$path_parts 
pathinfo('/path/emptyextension.');
var_dump($path_parts['extension']);

$path_parts pathinfo('/path/noextension');
var_dump($path_parts['extension']);
?>

以上例程的输出类似于:

string(0) ""

Notice: Undefined index: extension in test.php on line 6
NULL

注释

Note:

有关取得当前路径信息的说明,请阅读预定义变量一节。

Note:

pathinfo() is locale aware, so for it to parse a path containing multibyte characters correctly, the matching locale must be set using the setlocale() function.

参见

User Contributed Notes

Luis Villegas 01-Jul-2021 04:44
When you need to get the file extension to upload a file with a <form> POST method, try this way:

// $_FILES['archivo'] receives the <input> file (named 'archivo'), ['name'] gets the file name.

$nombre = $_FILES['archivo']['name'];

//['tmp_name] gets the temporal name of the file (not the real name), which will be used later

$nombre_temporal = $_FILES['archivo']['tmp_name'];

//Here is the magic of pathinfo to get the file extension

$extension = pathinfo($nombre, PATHINFO_EXTENSION);
$nombre_final = $nombre. ".". $extension;
// $ruta is where you want to save the file

$ruta = "subidos/".$nombre_final;
move_uploaded_file($nombre_temporal, $ruta);
info at kgsw dot de 25-May-2021 03:27
unexpected, but longtime (all versions?) consistent, behaviour with trailing slash (Linux):

with Linux I am used, to add a trailing slash,
or just to keep that of the command line completion by [TAB],
to avoid mistyping a path on cp or mv with a same filename instead of a directory
 
using CLI '$ php -a' the result is in the next line 
(but can also be done by script, webserver, etc.)

<?php // using php tags here only for syntax highlighting

// assuming getcwd() is /home/USER/ with existing subdir www.2021-05/
// cause path must exist, else 'false'
php > echo realpath('www.2021-05/');
/
home/USER/www.2021-05
 
php
> var_dump(pathinfo('/home/USER/www.2021-05/'));
array(
4) {
  [
"dirname"]=>    string(10) "/home/USER"
 
["basename"]=>   string(11) "www.2021-05"
 
["extension"]=>  string(7"2021-05"
 
["filename"]=>   string(3"www"
}

php > echo dirname('/home/USER/www.2021-05/');
/
home/USER
php
> echo basename('/home/USER/www.2021-05/');
www.2021-05
?>
with my own written functions, I would first split path from filename at the
_last_ slash (plus some extra for root-slash only);
 which would find NO filename, only dirname path, in that example

for cross reference:
once reported on Win2k -- https://bugs.php.net/bug.php?id=41834
said to be heritage -- https://bugs.php.net/bug.php?id=81079
Ozan Kurt 15-Jan-2020 10:15
extract(pathinfo("storage/example.pdf"));

echo $dirname; // "storage/"
echo $basename; // "example.pdf"
echo $extension; // "pdf"
echo $filename; // "example"
610010559 at qq dot com 15-Nov-2019 04:25
about the path, there are one thing you should note :
On Windows, both slash (/) and backslash (\) are used as directory separator character. In other environments, it is the forward slash (/).  (this explain is from basename() function part https://www.php.net/manual/en/function.basename.php)
example:
<?php
$path
= "http://www.test.com/a\b\c\filename.pdf";

echo
pathinfo($pdfUrl, PATHINFO_BASENAME);  //get basename
//output
//on window:  result is filename.pdf
//on Linux: result is a\b\c\filename.pdf (that is may not your expect)

//so in order to get same result in different system.  i will do below first.
$path = str_replace($path, '\\', '/'); //convert '\'  to '/'
?>
dev_zakaria at outlook dot com 15-Apr-2019 04:11
<?php

// suppose we are using a path like = www/myfiles/script.js

const FILE = "www/myfiles/script.js";

// print file name
echo pathinfo(FILE,PATHINFO_FILENAME)."\n";

// print file extension
echo pathinfo(FILE,PATHINFO_EXTENSION)."\n";

// print file Full name
echo pathinfo(FILE,PATHINFO_BASENAME)."\n";

// print file directory name
echo pathinfo(FILE,PATHINFO_DIRNAME)."\n";
guy dot paddock at gmail dot com 20-Dec-2018 03:08
Here is an enhanced version of pathinfo() that interprets multi-part extensions like tar.gz as one file extension:

<?php
function pathinfo_enhanced($file_path) {
 
$core_path_info = pathinfo($file_path);
 
$filename = $core_path_info['filename'];

  if (isset(
$core_path_info['extension'])) {
   
$extension = $core_path_info['extension'];
  } else {
   
$extension = '';
  }

 
$extension_parts = array();

  while (!empty(
$extension)) {
   
array_unshift($extension_parts, $extension);

   
$remaining_path_info = pathinfo($filename);
   
$filename = $remaining_path_info['filename'];

    if (isset(
$remaining_path_info['extension'])) {
     
$extension = $remaining_path_info['extension'];
    } else {
     
$extension = '';
    }
  }

 
$revised_path_info = array(
   
'filename'  => $filename,
   
'extension' => implode('.', $extension_parts),
  );

  return
array_merge($core_path_info, $revised_path_info);
}

// === EXAMPLES ===

// Directory; two extensions
$path = '/www/htdocs/inc/file.tar.gz';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";

// Directory; one extension
$path = '/www/htdocs/inc/file.tgz';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";

// Directory; no extension
$path = '/www/htdocs/inc/lib';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";

// No directory; one extension
$path = 'test.php';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";

// No directory; dot file
$path = '.example';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";

// Directory only
$path = '/www/htdocs/inc/';
$info = pathinfo_enhanced($path);

echo
"$path\n";
print_r($info);
echo
"\n";
Lori 21-Sep-2018 01:40
Simple example of pathinfo and array destructuring in PHP 7:
<?php
[ 'basename' => $basename, 'dirname' => $dirname ] = pathinfo('/www/htdocs/inc/lib.inc.php');

var_dump($basename, $dirname);

// result:
// string(11) "lib.inc.php"
// string(15) "/www/htdocs/inc"
?>
daniel_rhodes at yahoo dot co dot uk 23-Dec-2016 11:38
Note that pathinfo($somePath, PATHINFO_EXTENSION) will return '' (empty string) for both of these paths:

- some_random_file
- another_strange_file_ending_in_dot.

That's good, but then note that pathinfo($somePath, PATHINFO_FILENAME) won't end in the dot for 'another_strange_file_ending_in_dot.' - you'll need pathinfo($somePath, PATHINFO_BASENAME) to get the original filename ending in a dot.

Hope this helps!
smartdog at tut.by 08-Dec-2016 11:02
Lightweight way to get extension for *nix systems
<?php
function get_extension($path)
{
   
$c = preg_match('#[^\/]+\.([^\.]*)$#uis', $path, $tmp);
    return
$c ? $tmp[1] : null;
}
?>
this will return NULL for dotfiles (hidden files)

Testing:
<?php
$test
= array(
   
'/normal_dir/normal.foo',
   
'/double_ext.foo.bar',
   
'/.hidden/empty_ext.',
   
'/.hidden_dir/.hidden_file',
   
'/foo.bar/no_ext'
);
foreach(
$test as $path) {
   
var_dump(parse_extension($path));
}
?>

results:
string(3) "foo"
string(3) "bar"
string(0) ""
NULL
NULL

if you want to get all extensions (substring of file name after first dot) use another expression:
<?php
$c
= preg_match('#[^\.|\/]+\.([^\/]*)$#uis', $path, $tmp);
?>
498936940 at qq dot com 15-Jun-2016 03:02
Note:

pathinfo() is locale aware, so for it to parse a path containing multibyte characters correctly, the matching locale must be set using the setlocale() function.

Reality:
var_dump(pathinfo('中国人2016.xls'));
exit();
array(4) { 'dirname' => string(1) "." 'basename' => string(8) "2016.xls" 'extension' => string(3) "xls" 'filename' => string(4) "2016" }

Expect(Solve):
setlocale(LC_ALL, 'zh_CN.UTF-8');
var_dump(pathinfo('中国人2016.xls'));
exit();
array(4) { 'dirname' => string(1) "." 'basename' => string(17) "中国人2016.xls" 'extension' => string(3) "xls" 'filename' => string(13) "中国人2016" }
wxb0328 at hotmail dot com 19-May-2015 02:08
<?php

// your code goes here
echo phpversion();

print_r(pathinfo("/resources/img/stock/wxb001/美景.png"));

输出:
5.6.4
-2
Array
(
    [
dirname] => /resources/img/stock/wxb001
   
[basename] => 美景.png
   
[extension] => png
   
[filename] => 美景
)
但是在php5.3.3版本中
<?php

// your code goes here
echo phpversion();

print_r(pathinfo("/resources/img/stock/wxb001/美景.png"));
输出:
5.3.3
Array
(
    [
dirname] => /var/www/www.shima.jp.net/resources/img/stock/wxb001
   
[basename] => .png
   
[extension] => png
   
[filename] =>
)
bart at mediawave dot nl 23-Feb-2015 12:55
PHP equivalent for custom implementations. Will be nearly as fast or faster (with long paths):

<?php
$trimPath
= rtrim($path, '/');

$slashPos = strrpos($trimPath, '/');
if (
$slashPos !== false) {
   
$dirName = substr($trimPath, 0, $slashPos) ?: '/';
   
$baseName = substr($trimPath, $slashPos + 1);
} else {
   
$dirName = '.';
   
$baseName = $trimPath;
}

$dotPos = strrpos($baseName, '.');
if (
$dotPos !== false) {
   
$fileName = substr($baseName, 0, $dotPos);
   
$extension = substr($baseName, $dotPos + 1);
} else {
   
$extension = '';
   
$fileName = $baseName;
}
?>
ivan dot dossev at gmail dot com 21-Feb-2015 12:06
Note: dirname will be "." (meaning current directory) if the path is just a file name. (PHP 5.4.34)
<?php
var_dump
( pathinfo('file.ext', PATHINFO_DIRNAME) ); // string(1) "."
?>
cmartinezme at hotmail dot com 27-Jan-2015 12:46
Checked with version 5.5.12:

It works fine with filenames with utf-8 characters, pathinfo will strip them away:

<?php
print_r
(pathinfo("/mnt/files/飛兒樂團光茫.mp3"));
?>

.. will display:

Array
(
    [dirname] => /mnt/files
    [basename] => 飛兒樂團光茫.mp3
    [extension] => mp3
    [filename] => 飛兒樂團光茫
)
Jordan Doyle 04-May-2013 07:47
It's worth nothing that pathinfo returns foo/index.php for the directory when dealing with URLs like foo/index.php/bar
krkbpk at gmail dot com RamaKrishna Kothamasu 12-Feb-2013 03:44
//pathinfo function example
<?php
//passing single argument
echo "<pre>";
print_r(pathinfo("/home/ramki/ramki.pdf"));
echo
"</pre>";
//passing two agruments
$path=array(PATHINFO_DIRNAME,PATHINFO_BASENAME,PATHINFO_EXTENSION,PATHINFO_FILENAME);
foreach (
$path as $value)
echo
"<pre>".pathinfo("/home/ramki/ramki.pdf",$value)."</pre>";
?>
//output
/*
Array
(
    [dirname] => /home/ramki
    [basename] => ramki.pdf
    [extension] => pdf
    [filename] => ramki
)
/home/ramki
ramki.pdf
pdf
ramki
*/
Pietro Baricco 10-Feb-2012 04:00
Use this function in place of pathinfo to make it work with UTF-8 encoded file names too

<?php
function mb_pathinfo($filepath) {
   
preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im',$filepath,$m);
    if(
$m[1]) $ret['dirname']=$m[1];
    if(
$m[2]) $ret['basename']=$m[2];
    if(
$m[5]) $ret['extension']=$m[5];
    if(
$m[3]) $ret['filename']=$m[3];
    return
$ret;
}
?>
admin at torntech dot com 27-Jun-2011 09:39
pathinfo will return null if 0 or null is specified for the option argument.
So you'll need to define it's value manually if the option field is omitted, to provide the default functionality.

<?php

   
public function getFileInfo($source = null, $option = null){
        if(!
$option){
           
//1 + 2 + 4
           
$option = PATHINFO_DIRNAME + PATHINFO_BASENAME + PATHINFO_EXTENSION;
            if(
defined('PATHINFO_FILENAME'))
               
$option += PATHINFO_FILENAME; //8
       
}
        return
pathinfo($source, $option);
    }

   
$obj->getFileInfo("/test/file/someFile.txt");
?>
kc8yds at gmail dot com 18-Sep-2009 02:43
any type of url parse_url can handle this will get the extension of

pathinfo(parse_url('URL GOES HERE',PHP_URL_PATH),PATHINFO_EXTENSION)
jjoss at mail dot ru 04-Feb-2009 10:15
pathinfo() which can be used with UTF filenames.

<?php
 
function pathinfo_utf($path)
  {
    if (
strpos($path, '/') !== false) $basename = end(explode('/', $path));
    elseif (
strpos($path, '\\') !== false) $basename = end(explode('\\', $path));
    else return
false;
    if (empty(
$basename)) return false;

   
$dirname = substr($path, 0, strlen($path) - strlen($basename) - 1);

    if (
strpos($basename, '.') !== false)
    {
     
$extension = end(explode('.', $path));
     
$filename = substr($basename, 0, strlen($basename) - strlen($extension) - 1);
    }
    else
    {
     
$extension = '';
     
$filename = $basename;
    }

    return array
    (
     
'dirname' => $dirname,
     
'basename' => $basename,
     
'extension' => $extension,
     
'filename' => $filename
   
);
  }
?>
aalaap at gmail dot com 02-Feb-2009 07:58
Here is a simple function that gets the extension of a file. Simply using PATHINFO_EXTENSION will yield incorrect results if the path contains a query string with dots in the parameter names (for eg. &x.1=2&y.1=5), so this function eliminates the query string first and subsequently runs PATHINFO_EXTENSION on the clean path/url.

<?php
function extension($path) {
 
$qpos = strpos($path, "?");

  if (
$qpos!==false) $path = substr($path, 0, $qpos);
 
 
$extension = pathinfo($path, PATHINFO_EXTENSION);

  return
$extension;
}
?>
php [spat] hm2k.org 13-Jan-2009 04:27
A little compat for < 5.2

<?php

function pathinfo_filename($file) { //file.name.ext, returns file.name
   
if (defined('PATHINFO_FILENAME')) return pathinfo($file,PATHINFO_FILENAME);
    if (
strstr($file, '.')) return substr($file,0,strrpos($file,'.'));
}

?>
php-manual at spunts dot net 24-Dec-2008 09:19
For a good example of how platform independent this function is have a look at the different return values that Lostindream and I experienced. Mine is above and Lostindream's is below:

Array
(
    [dirname] => /www/psychicblast/images/1
    [basename] => my three girlfriends.jpg
    [extension] => jpg
)

Array
(
    [dirname] => /www/htdocs
    [basename] => index.html
    [extension] => html
    [filename] => index
)
z
benjaminhill at gmail dot com 02-Dec-2008 09:18
A warning: this function varies depending on the platform it is being run on.  For example, pathinfo('C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe') will return a different result when run through a winOS PHP platform (local development) vs. a server's UNIX-based OS.  A bit like the Locale settings, but unexpected.
Lostindream at atlas dot cz 19-Aug-2008 01:43
at example from "qutechie at gmail dot com" you can only replace function 'strpos' with 'strrpos'. (strrpos — Find position of last occurrence of a char in a string)

It's simple. For example:
<?php

function filePath($filePath)
{
 
$fileParts = pathinfo($filePath);

 if(!isset(
$fileParts['filename']))
 {
$fileParts['filename'] = substr($fileParts['basename'], 0, strrpos($fileParts['basename'], '.'));}
 
 return
$fileParts;
}
 
$filePath = filePath('/www/htdocs/index.html');
print_r($filePath);
?>

Output will be:
Array
(
    [dirname] => /www/htdocs
    [basename] => index.html
    [extension] => html
    [filename] => index
)
leons87_AT_hotmail_DOT_com 15-Aug-2008 04:47
qutechie at gmail dot com wrote a fix for support for filename in PHP 4; however it gets it wrong whenever you have a filename with a . in it (so foo.bar.jpg would return foo instead of foo.bar).

A fix would be:
<?php
if(!isset($path_parts['filename'])){
   
$reversed_filename = strrev( $path_parts['basename'] );
   
$path_parts['filename'] = strrev( substr( $reversed_filename, strpos( $reversed_filename, '.' ) + 1 ) );
}
?>

The idea is that you reverse the string and create a substring that starts after the first '.' and then reverse the result.
qutechie at gmail dot com 21-Jul-2008 06:29
Quick fix for lack of support for 'filename' in php4

<?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

// if php4
             
if(!isset($path_parts['filename'])){
               
$path_parts['filename'] = substr($path_parts['basename'], 0,strpos($path_parts['basename'],'.'));
              }

?>
christian dot reinecke at web dot de 24-Feb-2008 07:46
if you call pathinfo with a filename in url-style (example.php?with=parameter), make sure you remove the given parameters before, otherwise they will be returned as part of the extension.

extension => php?with=parameter
tom at foo-bar dot co dot uk 30-Jan-2008 06:48
Note that this function seems to just perform string operations, and will work even on a non-existent path, e.g.

<?php
print_r
(pathinfo('/no/where/file.txt'));
?>

which will output:
Array
(
    [dirname] => /no/where
    [basename] => file.txt
    [extension] => txt
    [filename] => file
)
davidblinco at gmail dot com 26-Jan-2008 07:27
This function is not perfect, but you can use it to convert a relative path to a URL.
Please email me if you can make any improvements.

<?php
function mapURL($relPath) {
   
$filePathName = realpath($relPath);
   
$filePath = realpath(dirname($relPath));
   
$basePath = realpath($_SERVER['DOCUMENT_ROOT']);
   
   
// can not create URL for directory lower than DOCUMENT_ROOT
   
if (strlen($basePath) > strlen($filePath)) {
        return
'';
    }
   
    return
'http://' . $_SERVER['HTTP_HOST'] . substr($filePathName, strlen($basePath));
}
?>
henrik at not-an-address dot com 21-Dec-2007 10:23
If you have filename with utf-8 characters, pathinfo will strip them away:

print_r(pathinfo("/mnt/files/飛兒樂團光茫.mp3"));

 .. will display:

Array
(
    [dirname] => /mnt/files
    [basename] => .mp3
    [extension] => mp3
    [filename] =>
)
mrnemesis at ntlworld dot com 19-Dec-2007 07:22
Note that in PHP 4 (if you're stuck using it), pathinfo only provides dirname, basename, and extension, but not filename. This function will not split a file's stem and extension for you.
cochise_chiracahua at hotmail.com 25-Nov-2005 11:55
Sometimes, it's interessant to get the basename without extension.
So, I appended a new entry 'basenameWE' (Basename Without Extension) to the returned array.

<?php

// pathinfo improved
function pathinfo_im($path) {
   
   
$tab = pathinfo($path);
   
   
$tab["basenameWE"] = substr($tab["basename"],0
   
,strlen($tab["basename"]) - (strlen($tab["extension"]) + 1) );
   
    return
$tab;
}

$my_path = "/var/www/html/example.html";

echo
"<pre>\n";
print_r( pathinfo_im($my_path) );
echo
"</pre>\n";

?>

Out :

Array
(
    [dirname] => /var/www/html
    [basename] => example.html
    [extension] => html
    [basenameWE] => example
)
n0dalus 08-Feb-2005 01:47
If a file has more than one 'file extension' (seperated by periods), the last one will be returned.
For example:
<?php
$pathinfo
= pathinfo('/dir/test.tar.gz');
echo
'Extension: '.$pathinfo['extension'];
?>
will produce:
Extension: gz

and not tar.gz
03-Dec-2004 04:39
If you want only the file extension, use this:
<?php
$extension
= substr(strrchr($filename, "."), 1);
?>
This is many times faster than using pathinfo() and getting the value from array.
rob at webdimension dot co dot uk 04-Oct-2004 06:48
Further to my previous post.

This affects servers that run PHP as a cgi module

If you have your own server:
You can use the AcceptPathInfo directive to force the core handler to accept requests with PATH_INFO and thereby restore the ability to use PATH_INFO in server-side includes.

Further information:
http://httpd.apache.org/docs-2.0/mod/core.html#acceptpathinfo
m-symons at home dot com 24-Aug-2001 06:54
Here's a neat wee function to grab the relative path to root (especially useful if you're using mock-directories to pass variables into scripts with mod_rewrite).  The function simply iterates through every occurence of "/" within the REQUEST_URI environment variable, appending "../" to the output for every instance:

<?php

function path_to_root($path) {

   
$pathinfo = pathinfo($path);
   
   
$deep = substr_count($pathinfo[dirname], "/");
   
   
$path_to_root = "./";
   
    for(
$i = 1; $i <= $deep; $i++) {
   
       
$path_to_root .= "../";
       
    }
   
    return
$path_to_root;
}

path_to_root($REQUEST_URI);

?>