Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/241.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 绝对路径和给定基本路径的相对文件名_Php_String_Path_Directory - Fatal编程技术网

Php 绝对路径和给定基本路径的相对文件名

Php 绝对路径和给定基本路径的相对文件名,php,string,path,directory,Php,String,Path,Directory,如何从绝对文件名和某些给定路径中获取相对文件名 例如: foo('/a/b/c/1.txt', '/a/d/e'); // '../../b/c/1.txt' foo('/a/b/../d/1.txt', '/a/d/e'); // '../c/1.txt' 这有一些本机函数吗 我的想法,如果没有: 规范化两个参数:需要使用一些realpath替换,因为文件可能不存在 从两个零件上切下公共零件 将$basepath中的其余部分添加为“..” 手动方式对于那个普通任务来说太重了。现在,

如何从绝对文件名和某些给定路径中获取相对文件名

例如:

foo('/a/b/c/1.txt', '/a/d/e');    // '../../b/c/1.txt'
foo('/a/b/../d/1.txt', '/a/d/e'); // '../c/1.txt'
这有一些本机函数吗

我的想法,如果没有:

  • 规范化两个参数:需要使用一些
    realpath
    替换,因为文件可能不存在
  • 从两个零件上切下公共零件
  • 将$basepath中的其余部分添加为“..”

手动方式对于那个普通任务来说太重了。

现在,我假设没有任何本机实现,并希望与大家分享我的实现

/**
 * realpath analog without filesystem check
 */
function str_normalize_path(string $path, string $sep = DIRECTORY_SEPARATOR): string {
    $parts = array_filter(explode($sep, $path));
    $stack = [];
    foreach ($parts as $part) {
        switch($part) {
            case '.': break;
            case '..': array_pop($stack); break; // excess '..' just ignored by array_pop([]) silency
            default: array_push($stack, $part);
        }
    }

    return implode($sep, $stack);
}

function str_relative_path(string $absolute, string $base, string $sep = DIRECTORY_SEPARATOR) {
    $absolute = str_normalize_path($absolute);
    $base = str_normalize_path($base);
    // find common prefix
    $prefix_len = 0;
    for ($i = 0; $i < min(mb_strlen($absolute), mb_strlen($base)); ++$i) {
        if ($absolute[$i] !== $base[$i]) break;
        $prefix_len++;
    }
    // cut common prefix
    if ($prefix_len > 0) {
        $absolute = mb_substr($absolute, $prefix_len);
        $base = mb_substr($base, $prefix_len);
    }
    // put '..'s for exit to closest common path
    $base_length = count(explode($sep, $base));
    $relative_parts = explode($sep, $absolute);
    while($base_length-->0) array_unshift($relative_parts, '..');
    return implode($sep, $relative_parts);
}

$abs = '/a/b/../fk1/fk2/../.././d//proj42/1.txt';
$base = '/a/d/fk/../e/f';

echo str_relative_path($abs, $base); // ../../proj42/1.txt
/**
*无文件系统检查的realpath模拟
*/
函数str_normalize_path(string$path,string$sep=DIRECTORY_SEPARATOR):string{
$parts=array_filter(分解($sep,$path));
$stack=[];
foreach($parts作为$part){
交换机(部分){
案例“.”:中断;
大小写“..”:数组\u pop($stack);break;//多余的“..”被数组\u pop([])沉默忽略
默认值:数组_push($stack,$part);
}
}
返回内爆($sep,$stack);
}
函数str_相对路径(字符串$absolute,字符串$base,字符串$sep=目录分隔符){
$absolute=str\u normalize\u路径($absolute);
$base=str\u normalize\u路径($base);
//查找公共前缀
$prefix_len=0;
对于($i=0;$i0){
$absolute=mb_substr($absolute,$prefix_len);
$base=mb\u substr($base$prefix\u len);
}
//将出口的“..”放在最近的公共路径上
$base_length=计数(分解($sep,$base));
$relative_parts=爆炸($sep,$absolute);
而($base_length-->0)数组_unshift($relative_parts,“…”);
返回内爆($sep,$relative_parts);
}
$abs='/a/b/./fk1/fk2/../../.././d///proj42/1.txt';
$base='/a/d/fk/./e/f';
echo str_相对路径($abs,$base);///proj42/1.txt