realpath

(PHP 4,PHP 5,PHP 7,PHP 8)

realpath - 返回规范化绝对路径名称

描述

realpath(string $path): string|false

realpath() 展开所有符号链接并解决对 /.//../ 以及输入 path 中多余的 / 字符的引用,并返回规范化的绝对路径名。

参数

path

正在检查的路径。

注意:

虽然必须提供一条路径,但值可以是空字符串。在这种情况下,该值将解释为当前目录。

返回值

成功时,返回规范化的绝对路径名。生成的路径将没有符号链接、/.//../ 组件。也会移除拖尾分隔符,例如 \/

realpath() 在失败时返回 false,例如,如果文件不存在。

注意:

正在运行的脚本必须对层级结构中的所有目录具有执行权限,否则 realpath() 将返回 false

注意:

对于不区分大小写的文件系统,realpath() 可能规范字符大小写,也可能不规范。

注意:

对于位于 Phar 内部的一个文件,realpath() 函数将不起作用,因为此类路径将是虚拟路径,而不是真实路径。

注意:

在 Windows 中,仅对目录中的结点和符号链接展开一个层级。

注意: 由于 PHP 的整数类型是有符号的,并且许多平台使用 32 位整数,因此某些文件系统函数对于大于 2GB 的文件可能返回意外的结果。

示例

示例 #1 realpath() 示例

<?php
chdir
('/var/www/');
echo
realpath('./../../etc/passwd') . PHP_EOL;

echo
realpath('/tmp/') . PHP_EOL;
?>

以上示例将输出

/etc/passwd
/tmp

示例 #2 在 Windows 中的 realpath()

在 Windows 中,realpath() 将把 Unix 风格路径更改为 Windows 风格。

<?php
echo realpath('/windows/system32'), PHP_EOL;

echo
realpath('C:\Program Files\\'), PHP_EOL;
?>

以上示例将输出

C:\WINDOWS\System32
C:\Program Files

另请参阅

添加笔记

用户贡献笔记 17 个笔记

Sven Arduwie
16 年前
因为 realpath() 不适用于不存在的文件,
我写了一个可以使用的函数。
它将 / 和 \\ 的(连续)出现替换为
DIRECTORY_SEPARATOR 中的内容,以及正常处理 /. 和 /..
get_absolute_path() 返回的路径不包含任何
位于第 0 位(字符串开头)或
第 -1 位(结尾)的(反向)斜杠
<?php
函数 get_absolute_path($path) {
$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
$absolutes = array();
foreach (
$parts as $part) {
if (
'.' == $part) continue;
if (
'..' == $part) {
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
return
implode(DIRECTORY_SEPARATOR, $absolutes);
}
?>

一个测试
<?php
var_dump
(get_absolute_path('this/is/../a/./test/.///is'));
?>
返回: string(14) "this/a/test/is"

如你所见,它也会生成尤达语。 :)
runeimp at gmail dot com
11 年前
需要一种方法来规范化可以处理超越初始文件夹引用的 .. 引用的虚拟路径。因此,我创建了以下内容。
<?php

函数 normalizePath($path)
{
$parts = array();// 数组,用于根据有效的路径构建一个新路径
$path = str_replace('\\', '/', $path);// 用正斜杠替换反斜杠
$path = preg_replace('/\/+/', '/', $path);// 合并多重斜杠为一个斜杠
$segments = explode('/', $path);// 收集路径段
$test = '';// 初始化测试变量
foreach($segments as $segment)
{
if(
$segment != '.')
{
$test = array_pop($parts);
if(
is_null($test))
$parts[] = $segment;
else if(
$segment == '..')
{
if(
$test == '..')
$parts[] = $test;

if(
$test == '..' || $test == '')
$parts[] = $segment;
}
else
{
$parts[] = $test;
$parts[] = $segment;
}
}
}
return
implode('/', $parts);
}
?>

将 /path/to/test/.././..//..///..///../one/two/../three/filename
转换为 ../../one/three/filename
moreau dot marc dot web at gmail dot com
4 年前
<?php

namespace MockingMagician\Organic\Helper;

class
Path
{
/**
* There is a method that deal with Sven Arduwie proposal https://php.net/manual/en/function.realpath.php#84012
* And runeimp at gmail dot com proposal https://php.net/manual/en/function.realpath.php#112367
* @param string $path
* @return string
*/
public static function getAbsolute(string $path): string
{
// Cleaning path regarding OS
$path = mb_ereg_replace('\\\\|/', DIRECTORY_SEPARATOR, $path, 'msr');
// Check if path start with a separator (UNIX)
$startWithSeparator = $path[0] === DIRECTORY_SEPARATOR;
// Check if start with drive letter
preg_match('/^[a-z]:/', $path, $matches);
$startWithLetterDir = isset($matches[0]) ? $matches[0] : false;
// Get and filter empty sub paths
$subPaths = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'mb_strlen');

$absolutes = [];
foreach (
$subPaths as $subPath) {
if (
'.' === $subPath) {
continue;
}
// if $startWithSeparator is false
// and $startWithLetterDir
// and (absolutes is empty or all previous values are ..)
// save absolute cause that's a relative and we can't deal with that and just forget that we want go up
if ('..' === $subPath
&& !$startWithSeparator
&& !$startWithLetterDir
&& empty(array_filter($absolutes, function ($value) { return !('..' === $value); }))
) {
$absolutes[] = $subPath;
continue;
}
if (
'..' === $subPath) {
array_pop($absolutes);
continue;
}
$absolutes[] = $subPath;
}

return
((
$startWithSeparator ? DIRECTORY_SEPARATOR : $startWithLetterDir) ?
$startWithLetterDir.DIRECTORY_SEPARATOR : ''
).implode(DIRECTORY_SEPARATOR, $absolutes);
}

/**
* Examples
*
* echo Path::getAbsolute('/one/two/../two/./three/../../two'); => /one/two
* echo Path::getAbsolute('../one/two/../two/./three/../../two'); => ../one/two
* echo Path::getAbsolute('../.././../one/two/../two/./three/../../two'); => ../../../one/two
* echo Path::getAbsolute('../././../one/two/../two/./three/../../two'); => ../../one/two
* echo Path::getAbsolute('/../one/two/../two/./three/../../two'); => /one/two
* echo Path::getAbsolute('/../../one/two/../two/./three/../../two'); => /one/two
* echo Path::getAbsolute('c:\.\..\one\two\..\two\.\three\..\..\two'); => c:/one/two
*
*/
}
David Beck
17 年前
以下是用于规范化包含相对路径的 URL 的函数。在从远程页面拉取链接时遇到了问题。

<?php

function canonicalize($address)
{
$address = explode('/', $address);
$keys = array_keys($address, '..');

foreach(
$keys AS $keypos => $key)
{
array_splice($address, $key - ($keypos * 2 + 1), 2);
}

$address = implode('/', $address);
$address = str_replace('./', '', $address);
}

$url = 'http://www.example.com/something/../else';
echo
canonicalize($url); //http://www.example.com/else

?>
plamen at dragiyski dot org
5 年前
realpath() 只是一个系统/函数库调用,由 OS 支持的实际 realpath() 函数。它并不处理作为字符串的路径,但也会解析符号链接。即使给定绝对路径,结果路径可能与输入明显不同。此批注中的任何函数都不能解决此问题。

realpath 手册页上的建议是查找现有的父目录。以下是一个示例
<?php
函数 resolvePath($path) {
if(
DIRECTORY_SEPARATOR !== '/') {
$path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
}
$search = explode('/', $path);
$search = array_filter($search, function($part) {
return
$part !== '.';
});
$append = array();
$match = false;
while(
count($search) > 0) {
$match = realpath(implode('/', $search));
if(
$match !== false) {
break;
}
array_unshift($append, array_pop($search));
};
if(
$match === false) {
$match = getcwd();
}
if(
count($append) > 0) {
$match .= DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $append);
}
return
$match;
}
?>

结果将为非存在的相对路径检索绝对路径。即便某个路径不存在,应该某个地方存在某个目录,为其获取实际路径。如果它不在相对路径内(即当前工作目录都不存在),getcwd() 将检索绝对路径,因此会返回某个绝对路径(尽管如此,PHP 进程仍有很大的问题)。
匿名者
12 年前
注意:如果你使用它来检查某个文件是否存在,它的路径将被缓存并返回 true,即使文件已被删除(改为使用 file_exists)。
[email protected]
19 年前
有时候您可能需要引用网站中的文件的绝对路径,而不是相对路径,但 realpath() 函数返回的是相对于服务器文件系统的路径,而不是相对于网站根目录的路径。

例如,realpath() 可能返回类似以下内容:

/home/yoursite/public_html/dir1/file.ext

您无法在 HTML 文档中使用此内容,因为 Web 服务器将找不到该文件。要执行此操作,您可以使用

<?php

function htmlpath($relative_path) {
$realpath=realpath($relative_path);
$htmlpath=str_replace($_SERVER['DOCUMENT_ROOT'],'',$realpath);
return
$htmlpath;
}

echo
'<img src="',htmlpath('../../relative/path/to/file.ext'),'" border=1>';

?>

它将返回类似以下内容:

<img src="/dir1/relative/path/to/file.ext" border=1>
Jrg Wagner
14 年前
请注意,此函数并不总是会删掉尾部斜杠!

LINUX(使用 PHP 5.2.11 测试)
---
realpath('.')
: string = "/myhttpdfolder"
realpath('./')
: string = "/myhttpdfolder"
realpath('fileadmin')
: string = "/myhttpdfolder/fileadmin"
realpath('fileadmin/')
: string = "/myhttpdfolder/fileadmin"

WINDOWS(使用 PHP 5.2.5 测试)
---
realpath('.')
: string = "C:\\myhttpdfolder"
realpath('./')
: string = "C:\\myhttpdfolder\\"
realpath('fileadmin')
: string = "C:\\myhttpdfolder\\fileadmin"
realpath('fileadmin/')
: string = "C:\\myhttpdfolder\\fileadmin\\"
https://stackoverflow.com/users/1397947/
6 年前
可能应该明确指出展开波浪线号不是由 realpath 执行的。
Vincent Par
9 年前
注意像下面的这种相对符号链接(Ubuntu 上的 ext4 文件系统)

vincent@vincent:~/Bureau/dirscan$ readlink sandbox/roulant/voiture/cabriolet/ln-loop-relative
../..

在这种情况下,realpath 可能返回 false

<?php
var_dump
(realpath('sandbox/roulant/voiture/cabriolet/ln-loop-relative'));
// => string(44) "/home/vincent/Bureau/dirscan/sandbox/roulant"
var_dump(realpath('sandbox/roulant/voiture/cabriolet/ln-loop-relative/moto'));
// => bool(false)
?>

但是你可以清除realpath缓存来修复此错误,方法如下

<?php
var_dump
(realpath('sandbox/roulant/voiture/cabriolet/ln-loop-relative'));
clearstatcache(true);
var_dump(realpath('sandbox/roulant/voiture/cabriolet/ln-loop-relative/moto'));
// => string(49) "/home/vincent/Bureau/dirscan/sandbox/roulant/moto"
?>
imagiro
12 年前
此处有一个小巧便捷的方法,用于计算从$from到$to的相对路径。注意:对于Windows,当$from和$to位于不同的磁盘上时,该方法无效。

<?php
function relativePath($from, $to, $ps = DIRECTORY_SEPARATOR)
{
$arFrom = explode($ps, rtrim($from, $ps));
$arTo = explode($ps, rtrim($to, $ps));
while(
count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0]))
{
array_shift($arFrom);
array_shift($arTo);
}
return
str_pad("", count($arFrom) * 3, '..'.$ps).implode($ps, $arTo);
}
?>
eion at robbmob dot com
8 年前
需要意识到 realpath() 无法处理隐藏的 Windows UNC 路径, 例如 \\servername\share$\folder\blah.txt,但其他 PHP 文件函数可以正常访问该文件。
Lars Scheithauer <l dot scheithauer at gmx dot de>
19 年前
该函数对于测试安全性漏洞也很不错。您可以禁止脚本访问特定目录中的文件以防止 "../../../etc/shadow" 及类似的攻击

<?php

// 声明基本目录以出于安全考量
// 切勿附加 “/” 后缀!
$basedir = '/var/www/cgi-bin/scriptfolder';

// 比较输入的路径和 basedir
$path_parts = pathinfo($_REQUEST['file_to_get']);
if (
realpath($path_parts['dirname']) != $basedir) {
/* 对破解尝试采取适当操作*/
die ('coding good - h4x1ng bad!');
}

?>

URL “script.php?file_to_get=../../../etc/shadow” 现在将导致错误。
php at keith tyler dot com
12 年前
请注意,在 Windows 中,根目录路径将在本地驱动器(不一定为 C:\)中解析。

比如

M:\>php -r "print realpath('/AUTOEXEC.BAT');"
[不打印任何内容,因为 M:\AUTOEXEC.BAT 不存在]



M:\>C
C:\>php -r "print realpath('/AUTOEXEC.BAT');"
C:\AUTOEXEC.BAT

相同的脚本,不同的响应取决于当前驱动器。

我倾向于坚持认为该函数 *应该* 使用 %SystemDrive% 的值作为“根目录”基准。
Leonard Challis
11 年前
在使用 realpath(和类似函数)时,请记住,PHP 将考虑 open_basedir 限制。因此,如果您执行类似操作

<?php
// httpdocs 文件夹中的 test.php
$path = realpath(dirname(__FILE__) . '/../application');
?>

且您的 open_basedir 设置为 httpdocs 文件夹和 tmp,则将会返回 false。您必须将其设置为更高级别(或关闭)才能正常工作。
belisoful at icloud dot com
1 年前
Sven Arduwie 的答案未经过测试,无法复制 realpath 的行为,但它是一个接近的解决方案。

该方法已经过单元测试,尽可能接近 realpath,但路径实际不必存在于系统中。

该方法采用相对路径并根据实际的当前工作目录正确地实现它们,但所有内容都可以是虚拟的。例如,“../someVirtualDir/./virtualFile.jpg”

<?php

public static function virtualpath($path): string
{
$path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
$len = strlen($path);
$relative = strpos($path, DIRECTORY_SEPARATOR);
if (!
$len || ($len > 0 && $path[0] == '.') || $relative !== 0) {
$path = getcwd() . DIRECTORY_SEPARATOR . $path;
}
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
$absolutes = [];
foreach (
$parts as $part) {
if (
'.' == $part) {
continue;
}
if (
'..' == $part) {
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
return
DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $absolutes);
}

?>
Enzo dot Barbaguelatta at alma dot cl
2 年前
需要注意的是,realpath 返回 false 的一个原因可能是路径不存在、有权限问题,或者操作系统(例如,SELinux)的安全模块阻止你检查路径。

如果你和我一样,在检查为什么 realpath 返回 false 时遇到了麻烦,请首先检查以下几点。
To Top