【问题标题】:Relative filename from absolute and given base path来自绝对路径和给定基本路径的相对文件名
【发布时间】:2018-09-30 20:04:15
【问题描述】:

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

例如:

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 替换,因为文件可能不存在。 example
  • 从两者中剪掉共同的部分
  • 将 $basepath 中的其余部分添加为“..”

手动方式对于该常见任务来说看起来太重了..

【问题讨论】:

    标签: php string path directory


    【解决方案1】:

    目前,我假设没有任何本机实现,并想分享我的实现。

    /**
     * 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
    

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 2018-01-22
      • 2010-12-11
      • 2010-09-15
      • 1970-01-01
      • 2013-07-14
      • 2010-12-17
      相关资源
      最近更新 更多