如何在 PHP 中加入文件系统路径字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1091107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:55:26  来源:igfitidea点击:

How to join filesystem path strings in PHP?

phpstringfile

提问by user89021

Is there a builtin function in PHP to intelligently join path strings? The function, given "abc/de/" and "/fg/x.php" as arguments, should return "abc/de/fg/x.php"; the same result should be given using "abc/de" and "fg/x.php" as arguments for that function.

PHP 中是否有内置函数可以智能地连接路径字符串?函数,给定“abc/de/”和“/fg/x.php”作为参数,应该返回“abc/de/fg/x.php”;使用“abc/de”和“fg/x.php”作为该函数的参数应该给出相同的结果。

If not, is there an available class? It could also be valuable for splitting paths or removing parts of them. If you have written something, may you share your code here?

如果没有,是否有可用的课程?它对于分割路径或删除部分路径也很有价值。如果你写了一些东西,你可以在这里分享你的代码吗?

It is ok to always use "/", I am coding for Linux only.

总是使用“/”是可以的,我只为 Linux 编码。

In Python there is os.path.join(), which is great.

在 Python 中有os.path.join(),这很棒。

采纳答案by deceze

Since this seems to be a popular question and the comments are filling with "features suggestions" or "bug reports"... All this code snippet does is join two strings with a slash without duplicating slashes between them. That's all. No more, no less. It does not evaluate actual paths on the hard disk nor does it actually keep the beginning slash (add that back in if needed, at least you can be sure this code always returns a string withoutstarting slash).

由于这似乎是一个流行的问题,并且评论中充斥着“功能建议”或“错误报告”......所有这些代码片段所做的就是用斜线连接两个字符串,而不会在它们之间重复斜线。就这样。不多也不少。它不评估硬盘上的实际路径,也不实际保留开头的斜杠(如果需要,将其添加回来,至少您可以确定此代码始终返回一个没有开头斜杠的字符串)。

join('/', array(trim("abc/de/", '/'), trim("/fg/x.php", '/')));

The end result will always be a path with no slashes at the beginning or end and no double slashes within. Feel free to make a function out of that.

最终结果将始终是一条开头或结尾没有斜线且内部没有双斜线的路径。随意制作一个函数。

EDIT: Here's a nice flexible function wrapper for above snippet. You can pass as many path snippets as you want, either as array or separate arguments:

编辑:这是上述代码段的一个很好的灵活函数包装器。您可以根据需要传递任意数量的路径片段,作为数组或单独的参数:

function joinPaths() {
    $args = func_get_args();
    $paths = array();
    foreach ($args as $arg) {
        $paths = array_merge($paths, (array)$arg);
    }

    $paths = array_map(create_function('$p', 'return trim($p, "/");'), $paths);
    $paths = array_filter($paths);
    return join('/', $paths);
}

echo joinPaths(array('my/path', 'is', '/an/array'));
//or
echo joinPaths('my/paths/', '/are/', 'a/r/g/u/m/e/n/t/s/');

:o)

:o)

回答by Riccardo Galli

function join_paths() {
    $paths = array();

    foreach (func_get_args() as $arg) {
        if ($arg !== '') { $paths[] = $arg; }
    }

    return preg_replace('#/+#','/',join('/', $paths));
}

My solution is simpler and more similar to the way Python os.path.join works

我的解决方案更简单,更类似于 Python os.path.join 的工作方式

Consider these test cases

考虑这些测试用例

array               my version    @deceze      @david_miller    @mark

['','']             ''            ''           '/'              '/'
['','/']            '/'           ''           '/'              '/'
['/','a']           '/a'          'a'          '//a'            '/a'
['/','/a']          '/a'          'a'          '//a'            '//a'
['abc','def']       'abc/def'     'abc/def'    'abc/def'        'abc/def'
['abc','/def']      'abc/def'     'abc/def'    'abc/def'        'abc//def'
['/abc','def']      '/abc/def'    'abc/def'    '/abc/def'       '/abc/def'
['','foo.jpg']      'foo.jpg'     'foo.jpg'    '/foo.jpg'       '/foo.jpg'
['dir','0','a.jpg'] 'dir/0/a.jpg' 'dir/a.jpg'  'dir/0/a.jpg'    'dir/0/a.txt'

回答by David Miller

@deceze's function doesn't keep the leading / when trying to join a path that starts with a Unix absolute path, e.g. joinPaths('/var/www', '/vhosts/site');.

@deceze 的函数在尝试加入以 Unix 绝对路径开头的路径时不会保留前导 /,例如joinPaths('/var/www', '/vhosts/site');.

function unix_path() {
  $args = func_get_args();
  $paths = array();

  foreach($args as $arg) {
    $paths = array_merge($paths, (array)$arg);
  }

  foreach($paths as &$path) {
    $path = trim($path, '/');
  }

  if (substr($args[0], 0, 1) == '/') {
    $paths[0] = '/' . $paths[0];
  }

  return join('/', $paths);
}

回答by mpen

My take:

我的看法:

function trimds($s) {
    return rtrim($s,DIRECTORY_SEPARATOR);
}

function joinpaths() {
    return implode(DIRECTORY_SEPARATOR, array_map('trimds', func_get_args()));
}

I'd have used an anonymous function for trimds, but older versions of PHP don't support it.

我会为 使用匿名函数trimds,但旧版本的 PHP 不支持它。

Example:

例子:

join_paths('a','\b','/c','d/','/e/','f.jpg'); // a\b\c\d\e\f.jpg (on Windows)


Updated April 2013March 2014May 2018:

更新 2013年4月2014 年 3 月2018 年 5 月

function join_paths(...$paths) {
    return preg_replace('~[/\\]+~', DIRECTORY_SEPARATOR, implode(DIRECTORY_SEPARATOR, $paths));
}

This one will correct any slashes to match your OS, won't remove a leading slash, and clean up and multiple slashes in a row.

这将更正任何斜杠以匹配您的操作系统,不会删除前导斜杠,并连续清理和多个斜杠。

回答by George Lund

If you know the file/directory exists, you can add extra slashes (that may be unnecessary), then call realpath, i.e.

如果您知道文件/目录存在,您可以添加额外的斜杠(这可能是不必要的),然后调用realpath,即

realpath(join('/', $parts));

realpath(join('/', $parts));

This is of course not quite the same thing as the Python version, but in many cases may be good enough.

这当然与 Python 版本不太一样,但在许多情况下可能已经足够好了。

回答by Chris J

An alternative is using implode()and explode().

另一种方法是使用implode()explode()

$a = '/a/bc/def/';
$b = '/q/rs/tuv/path.xml';

$path = implode('/',array_filter(explode('/', $a . $b)));

echo $path;  // -> a/bc/def/q/rs/tuv/path.xml

回答by stompydan

A different way of attacking this one:

一种不同的攻击方式:

function joinPaths() {
  $paths = array_filter(func_get_args());
  return preg_replace('#/{2,}#', '/', implode('/', $paths));
}

回答by Emanuele Del Grande

The solution below uses the logic proposed by @RiccardoGalli, but is improved to avail itself of the DIRECTORY_SEPARATORconstant, as @Qix and @FélixSaparelli suggested, and, more important, to trim each given elementto avoid space-only folder names appearing in the final path (it was a requirement in my case).

下面的解决方案使用@RiccardoGalli 提出的逻辑,但经过改进以利用DIRECTORY_SEPARATOR常量,正如@Qix 和@FélixSaparelli 所建议的那样,更重要的是,修剪每个给定元素以避免仅空格的文件夹名称出现在最终路径(这是我的要求)。

Regarding the escape of directory separator inside the preg_replace()pattern, as you can see I used the preg_quote()function which does the job fine.
Furthermore, I would replace mutiple separatorsonly (RegExp quantifier {2,}).

关于preg_replace()模式中目录分隔符的转义,如您所见,我使用了可以preg_quote()很好地完成工作的函数。
此外,我只会替换多个分隔符(RegExp 量词{2,})。

// PHP 7.+
function paths_join(string ...$parts): string {
    $parts = array_map('trim', $parts);
    $path = [];

    foreach ($parts as $part) {
        if ($part !== '') {
            $path[] = $part;
        }
    }

    $path = implode(DIRECTORY_SEPARATOR, $path);

    return preg_replace(
        '#' . preg_quote(DIRECTORY_SEPARATOR) . '{2,}#',
        DIRECTORY_SEPARATOR,
        $path
    );
}

回答by bumperbox

for getting parts of paths you can use pathinfo http://nz2.php.net/manual/en/function.pathinfo.php

要获取部分路径,您可以使用 pathinfo http://nz2.php.net/manual/en/function.pathinfo.php

for joining the response from @deceze looks fine

加入@deceze 的回复看起来不错

回答by EricP

This is a corrected version of the function posted by deceze. Without this change, joinPaths('', 'foo.jpg') becomes '/foo.jpg'

这是 deceze 发布的函数的更正版本。如果没有这个改变, joinPaths('', 'foo.jpg') 变成 '/foo.jpg'

function joinPaths() {
    $args = func_get_args();
    $paths = array();
    foreach ($args as $arg)
        $paths = array_merge($paths, (array)$arg);

    $paths2 = array();
    foreach ($paths as $i=>$path)
    {   $path = trim($path, '/');
        if (strlen($path))
            $paths2[]= $path;
    }
    $result = join('/', $paths2); // If first element of old path was absolute, make this one absolute also
    if (strlen($paths[0]) && substr($paths[0], 0, 1) == '/')
        return '/'.$result;
    return $result;
}