如果文件夹不存在,则创建它

758
我在使用Bluehost安装WordPress时遇到了一些问题,因为上传文件夹wp-content/uploads不存在,导致我的WordPress主题出现错误。
显然,cPanel的WordPress安装程序没有创建这个文件夹,而HostGator则有。
因此,我需要在我的主题中添加代码来检查该文件夹是否存在,如果不存在则创建它。

17
如果('path/to/directory')目录不存在,就会创建一个名为'path/to/directory'的目录,并授予权限为0777。 - I am the Most Stupid Person
21个回答

1500

尝试使用 mkdir

if (!file_exists('path/to/directory')) {
    mkdir('path/to/directory', 0777, true);
}

请注意,0777已经是目录的默认模式,并且仍然可以通过当前umask进行修改。


16
你错过了“recursive”标志 - 参见Satish的答案。 - Francois Bourgeois
141
is_dir() 比 file_exists() 更快。 - pliashkou
55
@YuryPliashkou 好吧,也许可以,但如果已经有一个同名的文件,它就不起作用了。 - Gumbo
5
如果路径 path/to 中存在名为 'directory' 的文件,is_dir 将返回 true,但 file_exists 将返回 false? - Igor L.
13
file_exists — 检查文件或目录是否存在
is_file — 判断文件名是否为常规文件
is_dir — 判断文件名是否为目录
- TarranJones
显示剩余8条评论

181

这里是缺失的部分。您需要在 mkdir 调用中传递“recursive”标志作为第三个参数(布尔值 true),如下所示:

mkdir('path/to/directory', 0755, true);

13
“recursive”标志是布尔值第三个参数true - ahnbizcad

75

使用这样的帮助函数:

function makeDir($path)
{
     $ret = mkdir($path); // use @mkdir if you want to suppress warnings/errors
     return $ret === true || is_dir($path);
}

如果目录成功创建或已存在,则返回true,如果无法创建目录,则返回false

更好的替代方法是这个(不应该出现任何警告):

function makeDir($path)
{
     return is_dir($path) || mkdir($path);
}

6
如果你移除@并使用正确的is_dir检查,我会点赞 :) 如果能检查父目录是否可写,就更好了,这样可以使帮助函数更加完善。 - Pekka
使用@来抑制错误会影响性能。最好像Gumbo一样检查它是否已经存在。 - Simon
1
无论是否进行错误抑制,我倾向于在第一个示例中使用-1。第二个示例要好得多,以至于第一个示例毫无意义。 - Justin Johnson
这段代码很难阅读,只是为了将其放在一行上。被接受的答案更清晰易懂。 - MikeKulls

74

以下内容更通用,因为这个问题在谷歌上经常出现。虽然细节可能有所不同,但问题的标题更加普遍。

/**
 * recursively create a long directory path
 */
function createPath($path) {
    if (is_dir($path)) 
        return true;
    $prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 );
    $return = createPath($prev_path);
    return ($return && is_writable($prev_path)) ? mkdir($path) : false;
}

这段代码将获取一个路径,可能包含许多未创建的目录,并一路向上查找现有目录。然后它将尝试在该目录中创建下一个目录,并继续进行直到创建所有目录。如果成功,则返回true。

可以通过提供停止级别来改进此代码,以便在超出用户文件夹或其他限制时失败,并包括权限设置。


1
@phazei,我因为这行代码 $return = createPath($prev_path); 出现了未定义函数的调用错误。 - Battousai
感谢 @phazei :) - Alex

37

创建文件夹的更快方式:

if (!is_dir('path/to/directory')) {
    mkdir('path/to/directory', 0777, true);
}

如果在该路径下存在一个名为“directory”的文件,这将导致错误。 - Guney Ozsan

25

递归创建目录路径:

function makedirs($dirpath, $mode=0777) {
    return is_dir($dirpath) || mkdir($dirpath, $mode, true);
}

受 Python 的 os.makedirs() 启发


它以什么方式是递归的?不是在函数调用中(它没有调用自身)?操作原理是什么?为什么有效?mkdir是否递归执行?您能否在回答中详细说明一下?(但不包括“编辑:”,“更新:”或类似内容 - 答案应该看起来像今天编写的。) - Peter Mortensen
Satish Gadhave的回答中有一些解释。 - Peter Mortensen

22

最佳方法是使用wp_mkdir_p函数。此函数将以递归方式创建一个具有正确权限的文件夹。

此外,你可以跳过文件夹存在条件,因为该函数返回:

  • 当目录被创建或之前已存在时,返回true
  • 如果无法创建目录,则返回false

例如:

$path = 'path/to/directory';
if ( wp_mkdir_p( $path ) ) {
    // Directory exists or was created.
}

更多信息:https://developer.wordpress.org/reference/functions/wp_mkdir_p/


4
值得一提的是,wp_mkdir_p()函数如果目录已经存在也会返回true,因此您不需要进行任何额外的file_exists()检查。此外,它会尽力设置适当的目录权限。我会总是使用这个函数,而不是重复发明轮子。 - Ihor Vorotnov
1
值得一提的是,这是一个WordPress特定的函数,而不是通用的PHP函数。话虽如此,你完全可以从WordPress开发者网站上复制该函数。 - James John McGuire 'Jahmic'

12

在WordPress内还有非常方便的函数wp_mkdir_p,它可以递归地创建目录结构。

参考来源:

function wp_mkdir_p( $target ) {
    $wrapper = null;

    // Strip the protocol
    if( wp_is_stream( $target ) ) {
        list( $wrapper, $target ) = explode( '://', $target, 2 );
    }

    // From php.net/mkdir user contributed notes
    $target = str_replace( '//', '/', $target );

    // Put the wrapper back on the target
    if( $wrapper !== null ) {
        $target = $wrapper . '://' . $target;
    }

    // Safe mode fails with a trailing slash under certain PHP versions.
    $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
    if ( empty($target) )
        $target = '/';

    if ( file_exists( $target ) )
        return @is_dir( $target );

    // We need to find the permissions of the parent folder that exists and inherit that.
    $target_parent = dirname( $target );
    while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
        $target_parent = dirname( $target_parent );
    }

    // Get the permission bits.
    if ( $stat = @stat( $target_parent ) ) {
        $dir_perms = $stat['mode'] & 0007777;
    } else {
        $dir_perms = 0777;
    }

    if ( @mkdir( $target, $dir_perms, true ) ) {

        // If a umask is set that modifies $dir_perms, we'll have to re-set the $dir_perms correctly with chmod()
        if ( $dir_perms != ( $dir_perms & ~umask() ) ) {
            $folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
            for ( $i = 1; $i <= count( $folder_parts ); $i++ ) {
                @chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
            }
        }

        return true;
    }

    return false;
}

关于“递归创建目录结构”:这是否意味着普通的PHP函数无法完成此任务? - Peter Mortensen

9

我需要为登录站点做同样的事情。我需要创建一个带有两个变量的目录。

$directory是我想要在其中创建另一个子文件夹的主文件夹,该子文件夹包含用户许可证号码。

include_once("../include/session.php");

$lnum = $session->lnum; // Users license number from sessions
$directory = uploaded_labels; // Name of directory that folder is being created in

if (!file_exists($directory . "/" . $lnum)) {
    mkdir($directory . "/" . $lnum, 0777, true);
}

5

这是最新的解决方案,不需要错误抑制:

if (!is_dir('path/to/directory')) {
    mkdir('path/to/directory');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接