ChatGPT解决这个技术问题 Extra ChatGPT

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

我遇到过一些使用 Bluehost 安装 WordPress 的案例,因为上传文件夹 wp-content/uploads 不存在,我的 WordPress 主题遇到了错误。

显然 Bluehost cPanel WordPress 安装程序不会创建此文件夹,但 HostGator 会。

所以我需要将代码添加到我的主题中,以检查文件夹并以其他方式创建它。

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

r
reformed

试试这个,使用 mkdir

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

请注意,0777 已经是目录的默认模式,并且可能仍会被当前的 umask 修改。


您错过了“递归”标志 - 请参阅 Satish 的回答。
is_dir() 比 file_exists() 快一点
@YuryPliashkou 是的,但如果已经有一个具有该名称的文件,它就不起作用。
这里的问题:所以如果在 path/to 中有一个名为 'directory' 的文件,is_dir 会返回 true,但 file_exists 会返回 false?
file_exists - 检查文件或目录是否存在 is_file - 判断文件名是否为常规文件 is_dir - 判断文件名是否为目录
r
reformed

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

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

'recursive' 标志是布尔第三个参数 true
P
Peter Mortensen

这是一些更普遍的东西,因为它出现在谷歌上。虽然细节更具体,但这个问题的标题更普遍。

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

可以通过提供停止级别来改进它,因此如果超出用户文件夹或其他内容并包含权限,它就会失败。


@phazei 由于 $return = createPath($prev_path); 行,我得到了对未定义函数的调用
谢谢@phazei :)
P
Peter Mortensen

使用这样的辅助函数:

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);
}

如果您删除 @ 并用正确的 is_dir 检查替换它,我的赞成票就是您的 :) 检查父目录 is_writable() 是否具有防水辅助功能的奖励积分。
使用 @ 来抑制错误会影响性能。最好检查一下它不像 Gumbo 那样已经存在
不管错误抑制如何,对于第一个示例,我倾向于 -1。第二个好多了,第一个毫无意义。
仅仅为了将其放在 1 行上,这很难阅读代码。接受的答案要清楚得多。
P
Peter Mortensen

创建文件夹的更快方法:

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

如果该路径中有一个名为“目录”的文件,这将产生错误。
P
Peter Mortensen

递归创建目录路径:

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

受 Python 的 os.makedirs() 启发


它以什么方式递归?不在函数调用中(它不调用自身)?工作原理是什么?为什么有效? mkdir 是否递归执行?你能在你的答案中详细说明一下吗? (但没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。)
Satish Gadhave's answer 中有一些解释。
W
WP Punk

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

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

当目录被创建或之前存在时为真

如果您无法创建目录,则返回 false。

例子:

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

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


值得一提的是,如果目录已经存在,wp_mkdir_p() 也会返回 true,因此您不需要任何额外的 file_exists() 检查。此外,它会尽力设置适当的目录权限。我总是使用这个功能而不是重新发明轮子。
P
Peter Mortensen

在 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 函数不能做到这一点?
P
Peter Mortensen

对于登录站点,我需要同样的东西。我需要创建一个包含两个变量的目录。

$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);
}

A
Andreas

这是没有错误抑制的最新解决方案:

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

U
Usman Ahmed

对于您关于 WordPress 的具体问题,请使用以下代码:

if (!is_dir(ABSPATH . 'wp-content/uploads')) wp_mkdir_p(ABSPATH . 'wp-content/uploads');

函数参考:WordPress wp_mkdir_pABSPATH 是返回 WordPress 工作目录路径的常量。

还有另一个名为 wp_upload_dir() 的 WordPress 函数。它返回上传目录路径并创建一个文件夹(如果尚不存在)。

$upload_path = wp_upload_dir();

以下代码一般适用于 PHP。

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

函数参考:PHP is_dir()


对于 WordPress 的使用,更安全的使用方式是 wp_get_upload_dir() 函数。
@IvijanStefanStipić 你能解释一下为什么你认为我的代码不安全吗?我故意不使用 wp_get_upload_dir() 函数。所以用户可以创建他想要的任何文件夹,而不仅仅是上传文件夹。
该函数返回上传文件夹的基本目录和基本 url。如果有人使用安全插件或 CDN 并想要更改它,它将中继到该功能。我开发 WP 插件大约 8 年,相信我,在生产中你需要提前考虑。您只需要添加自定义文件夹并在不存在时创建。
为什么它在 WordPress 中与普通 PHP 不同?是绝对必要的吗?更安全? (不是反问。)
N
Nikunj Kathrotiya
$upload = wp_upload_dir();
$upload_dir = $upload['basedir'];
$upload_dir = $upload_dir . '/newfolder';
if (! is_dir($upload_dir)) {
   mkdir( $upload_dir, 0700 );
}

P
Peter Mortensen

如果您想避免 file_existsis_dir 的问题,我建议您查看 here

我试过了,如果目录不存在,它只会创建目录。它不关心是否存在具有该名称的文件。

/* Creates the directory if it does not exist */
$path_to_directory = 'path/to/directory';
if (!file_exists($path_to_directory) && !is_dir($path_to_directory)) {
    mkdir($path_to_directory, 0777, true);
}

P
Peter Mortensen

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

考虑到问题的环境。

WordPress。

虚拟主机服务器。

假设它是 Linux,而不是运行 PHP 的 Windows。

并引用自:mkdir

bool mkdir ( string $pathname [, int $mode = 0777 [, bool $recursive = FALSE [, resource $context ]]] )

手册说唯一需要的参数是 $pathname

所以,我们可以简单地编码:

<?php
    error_reporting(0); 

    if(!mkdir('wp-content/uploads')){
        // Todo
    }
?>

解释:

除非需要,我们不必传递任何参数或检查文件夹是否存在甚至传递模式参数;原因如下:

该命令将创建具有 0755 权限(共享主机文件夹的默认权限)或 0777(该命令的默认权限)的文件夹。

模式在运行 PHP 的 Windows 主机上被忽略。

mkdir 命令已经有一个内置的检查器来检查文件夹是否存在;所以我们只需要检查返回 True|False ;这不是错误;这只是一个警告,默认情况下在托管服务器上禁用警告。

根据速度,如果禁用警告,这会更快。

这只是另一种研究问题的方式,而不是要求更好或最优化的解决方案。

它在 PHP 7、生产服务器和 Linux 上进行了测试


M
Mayur Kukadiya
if (!is_dir('path_directory')) {
    @mkdir('path_directory');
}

使用错误抑制,无需检查目录是否存在
处理错误比抑制错误更好。如果这失败了,你永远不会知道为什么,并且必须研究它
在高度并发/多线程环境中,建议抑制错误。可能会出现竞争条件,其中两个或多个线程会将 is_dir() 评估为 false 并尝试创建目录。第一个线程可以毫无问题地创建它,但其他线程将无法创建它,因为该目录已经存在。为避免错过实际失败的目录创建,您应该在再次调用 @mkdir() 后检查目录是否存在。
U
ULIDU THEERAKE

干得好。

if (!is_dir('path/to/directory')) {
    if (!mkdir('path/to/directory', 0777, true) && !is_dir('path/to/directory')) {
        throw new \RuntimeException(sprintf('Directory "%s" was not created', 'path/to/directory'));
    }
}

PHPStorm(带有 PHP 检查)给出了这个建议 ;-) 顺便说一句。您可以将外部 if 合并到内部: if (!is_dir(...) && !mkdir(...) && !is_dir(...)) ...
@aProgger 如果将它们分开时看起来会更好。许多程序员不会合并 if 语句。
这是一个品味问题。我会合并它们,甚至踢牙套,得到一个衬里。但我很好奇。你会只分开第一个 !is_dir 还是最后一个?
哇,在所有答案中,这是唯一一个具有有意义的错误处理的强大答案。恭喜,你赢得了我的互联网积分。
s
simhumileco

你也可以试试:

$dirpath = "path/to/dir";
$mode = "0764";
is_dir($dirpath) || mkdir($dirpath, $mode, true);

J
Jens Törnell

作为对当前解决方案的补充,实用功能。

function createDir($path, $mode = 0777, $recursive = true) {
  if(file_exists($path)) return true;
  return mkdir($path, $mode, $recursive);
}

createDir('path/to/directory');

如果已存在或成功创建,则返回 true。否则返回false。


P
Peter Mortensen

我们应该总是模块化我们的代码,我在下面写了同样的检查......

我们首先检查目录。如果目录不存在,我们创建目录。

$boolDirPresents = $this->CheckDir($DirectoryName);

if (!$boolDirPresents) {
        $boolCreateDirectory = $this->CreateDirectory($DirectoryName);
        if ($boolCreateDirectory) {
        echo "Created successfully";
      }
  }

function CheckDir($DirName) {
    if (file_exists($DirName)) {
        echo "Dir Exists<br>";
        return true;
    } else {
        echo "Dir Not Absent<br>";
        return false;
    }
}
     
function CreateDirectory($DirName) {
    if (mkdir($DirName, 0777)) {
        return true;
    } else {
        return false;
    }
}

N
Nasir Khan

您首先需要检查目录是否存在 file_exists('path_to_directory')

然后使用 mkdir(path_to_directory) 创建目录

mkdir( string $pathname [, int $mode = 0777 [, bool $recursive = FALSE [, resource $context ]]] ) : bool

关于mkdir() here的更多信息

完整代码在这里:

$structure = './depth1/depth2/depth3/';
if (!file_exists($structure)) {
    mkdir($structure);
}