开发者

Extract direct sub directory from path string

开发者 https://www.devze.com 2022-12-29 06:40 出处:网络
I need to extract the name of the direct sub directory from a full path string. For example, say we have:

I need to extract the name of the direct sub directory from a full path string.

For example, say we have:

$str = "dir1/dir2/dir3/dir4/filename.ext";
$dir = "dir1/dir2";

Then the name of the sub-directory in the $str path relative to $dir would be "dir3". Note that $dir never has '/' at the ends.

So the function should be:

$subdir = getsubdir($str,$dir);
echo $subdir; // Outputs "dir3"

If $dir="dir1" then the output would be "dir2". If $dir="dir1/dir2/d开发者_Python百科ir3/dir4" then the output would be "" (empty). If $dir="" then the output would be "dir1". Etc..

Currently this is what I have, and it works (as far as I've tested it). I'm just wondering if there's a simpler way since I find I'm using a lot of string functions. Maybe there's some magic regexp to do this in one line? (I'm not too good with regexp unfortunately).

function getsubdir($str,$dir) {
    // Remove the filename
    $str = dirname($str);

    // Remove the $dir
    if(!empty($dir)){
        $str = str_replace($dir,"",$str);
    }

    // Remove the leading '/' if there is one
    $si = stripos($str,"/");
    if($si == 0){
        $str = substr($str,1);
    }

    // Remove everything after the subdir (if there is anything)
    $lastpart = strchr($str,"/");
    $str = str_replace($lastpart,"",$str);

    return $str;
}

As you can see, it's a little hacky in order to handle some odd cases (no '/' in input, empty input, etc). I hope all that made sense. Any help/suggestions are welcome.

Update (altered solution):

Well Alix Axel had it spot on. Here's his solution with slight tweaks so that it matches my exact requirements (eg: it must return a string, only directories should be outputted (not files))

function getsubdir($str,$dir) {
    $str = dirname($str);
    $temp = array_slice(array_diff(explode('/', $str), explode('/', $dir)), 0, 1);
    return $temp[0];   
}


Here you go:

function getSubDir($dir, $sub)
{
    return array_slice(array_diff(explode('/', $dir), explode('/', $sub)), 0, 1);
}

EDIT - Foolproof implementation:

function getSubDirFoolproof($dir, $sub)
{
    /*
    This is the ONLY WAY we have to make SURE that the
    last segment of $dir is a file and not a directory.
    */
    if (is_file($dir))
    {
        $dir = dirname($dir);
    }

    // Is it necessary to convert to the fully expanded path?
    $dir = realpath($dir);
    $sub = realpath($sub);

    // Do we need to worry about Windows?
    $dir = str_replace('\\', '/', $dir);
    $sub = str_replace('\\', '/', $sub);

    // Here we filter leading, trailing and consecutive slashes.
    $dir = array_filter(explode('/', $dir));
    $sub = array_filter(explode('/', $sub));

    // All done!
    return array_slice(array_diff($dir, $sub), 0, 1);
}


How about splitting the whole thing into an array:

$fullpath = explode("/", "dir1/dir2/dir3/dir4/filename.ext");
$fulldir  = explode("/", "dir1/dir2");

// Will result in array("dir1","dir2","dir3", "dir4", "filename.ext");
// and            array("dir1", "dir2");

you should then be able to use array_diff():

$remainder = array_diff($fullpath, $fulldir);

// Should return array("dir3", "dir4", "filename.ext");

then, getting the direct child is easy:

echo $remainder[0];

I can't test this right now but it should work.


Here's a similar "short" solution, this time using string functions rather than array functions. If there is no corresponding part to be gotten from the string, getsubdir will return FALSE. The strtr segment is a quick way to escape the percents, which have special meaning to sscanf.

function getsubdir($str, $dir) {
    return sscanf($str, strtr($dir, '%', '%%').'/%[^/]', $name) === 1 ? $name : FALSE;
}

And a quick test so you can see how it behaves:

$str = "dir1/dir2/dir3/dir4/filename.ext";
var_dump(
    getSubDir($str, "dir1"),
    getSubDir($str, "dir1/dir2/dir3"),
    getSubDir($str, "cake")
);
// string(4) "dir2"
// string(4) "dir4"
// bool(false)
0

精彩评论

暂无评论...
验证码 换一张
取 消