如何检查目录是否存在?“ is_dir”,“ file_exists”还是两者?


329

如果目录不存在,我想创建一个目录。

is_dir为此目的是否足够使用?

if ( !is_dir( $dir ) ) {
    mkdir( $dir );       
}

还是应该结合is_dir使用file_exists

if ( !file_exists( $dir ) && !is_dir( $dir ) ) {
    mkdir( $dir );       
} 

3
布尔运算符OR应该为AND,在PHP中,其写为​​&&
Ivo Renkema 2013年

15
@IvoRenkema PHP也支持or/ and除了||/ &&
卡米洛·马丁

1
运算符&&在这里没有用,因为如果文件不存在(!file_exists($dir) == true),请确保它不是目录。并且如果文件存在,!is_dir($dir)将不会被检查,因为!file_exists($dir)会返回false并且&&操作员短路
Boolean_Type

4
我认为运算符应为OR。
Mojtaba

与&&一起使用,对我来说非常适合
FABBRj

Answers:


220

两者在Unix系统上都将返回true-在Unix中,所有内容都是文件,包括目录。但是要测试该名称是否被采用,您应该同时检查两者。可能会有一个名为“ foo”的常规文件,这将阻止您创建目录名称“ foo”。


37
不要忘记检查is_writable是否也可以
-Drewdin

10
@Drewdin您想检查父母is_writable吗?
马修·沙利

133
$dirname = $_POST["search"];
$filename = "/folder/" . $dirname . "/";

if (!file_exists($filename)) {
    mkdir("folder/" . $dirname, 0777);
    echo "The directory $dirname was successfully created.";
    exit;
} else {
    echo "The directory $dirname exists.";
}

46
回声非常说明……
凯– SE是邪恶的

13
考虑到它需要后期输入并按原样使用它,再加上0777 dir,根本就不那么安全; P
sEver 2013年

2
更严重的是,可以清理$ dirname并将权限设置为0755。此外,还添加了一些.htaccess指令。OWASP上还有其他一些建议: owasp.org
James P.

# The following directives force the content-type application/octet-stream # and force browsers to display a download dialog for non-image files. # This prevents the execution of script files in the context of the website: #ForceType application/octet-stream Header set Content-Disposition attachment <FilesMatch "(?i)\.(gif|jpe?g|png)$"> ForceType none Header unset Content-Disposition </FilesMatch> # The following directive prevents browsers from MIME-sniffing the content-type. # This is an important complement to the ForceType directive above: Header set X-Content-Type-Options nosniff
James P.

7
使用时mkdir-为什么不只传递'$ filename'?
Howdy_McGee 2014年

17

我认为realpath()可能是验证路径是否存在的最佳方法 http://www.php.net/realpath

这是一个示例函数:

<?php
/**
 * Checks if a folder exist and return canonicalized absolute pathname (long version)
 * @param string $folder the path being checked.
 * @return mixed returns the canonicalized absolute pathname on success otherwise FALSE is returned
 */
function folder_exist($folder)
{
    // Get canonicalized absolute pathname
    $path = realpath($folder);

    // If it exist, check if it's a directory
    if($path !== false AND is_dir($path))
    {
        // Return canonicalized absolute pathname
        return $path;
    }

    // Path/folder does not exist
    return false;
}

相同功能的简短版本

<?php
/**
 * Checks if a folder exist and return canonicalized absolute pathname (sort version)
 * @param string $folder the path being checked.
 * @return mixed returns the canonicalized absolute pathname on success otherwise FALSE is returned
 */
function folder_exist($folder)
{
    // Get canonicalized absolute pathname
    $path = realpath($folder);

    // If it exist, check if it's a directory
    return ($path !== false AND is_dir($path)) ? $path : false;
}

输出示例

<?php
/** CASE 1 **/
$input = '/some/path/which/does/not/exist';
var_dump($input);               // string(31) "/some/path/which/does/not/exist"
$output = folder_exist($input);
var_dump($output);              // bool(false)

/** CASE 2 **/
$input = '/home';
var_dump($input);
$output = folder_exist($input);         // string(5) "/home"
var_dump($output);              // string(5) "/home"

/** CASE 3 **/
$input = '/home/..';
var_dump($input);               // string(8) "/home/.."
$output = folder_exist($input);
var_dump($output);              // string(1) "/"

用法

<?php

$folder = '/foo/bar';

if(FALSE !== ($path = folder_exist($folder)))
{
    die('Folder ' . $path . ' already exist');
}

mkdir($folder);
// Continue do stuff

2
对于遇到此问题的任何人,我相信realpath在运行时会缓存文件夹,因此,如果运行一次,则该文件夹将在此之后被删除,如果再次运行,它可能不会返回false。
2015年

2
但是file_exists也是如此
Sebas

7

有问题的帖子的第二个变种不好,因为,如果您已经有相同名称的文件,但它不是目录,!file_exists($dir)则会返回false,不会创建文件夹,因此"failed to open stream: No such file or directory"会发生错误。在Windows中有“文件”和“文件夹”类型之间的差异,因此需要使用file_exists(),并is_dir()在同一时间,为前:

if (file_exists('file')) {
    if (!is_dir('file')) { //if file is already present, but it's not a dir
        //do something with file - delete, rename, etc.
        unlink('file'); //for example
        mkdir('file', NEEDED_ACCESS_LEVEL);
    }
} else { //no file exists with this name
    mkdir('file', NEEDED_ACCESS_LEVEL);
}

3
$year = date("Y");   
$month = date("m");   
$filename = "../".$year;   
$filename2 = "../".$year."/".$month;

if(file_exists($filename)){
    if(file_exists($filename2)==false){
        mkdir($filename2,0777);
    }
}else{
    mkdir($filename,0777);
}

1
您可以检查完整路径,如果不存在,请使用mkdir递归创建:if(!file_exists($ filename2)){mkdir($ filename2,0777,true); }此外,如果$ filename不存在,您的代码将永远不会创建完整路径...
Niels R.

3
$save_folder = "some/path/" . date('dmy');

if (!file_exists($save_folder)) {
   mkdir($save_folder, 0777);
}

3
设置chmod 777绝不是一个好主意。755就足够了。
Oldskool

2

在0777之后添加true

<?php
    $dirname = "small";
    $filename = "upload/".$dirname."/";

    if (!is_dir($filename )) {
        mkdir("upload/" . $dirname, 0777, true);
        echo "The directory $dirname was successfully created.";
        exit;
    } else {
        echo "The directory $dirname exists.";
    }
     ?>

1

好吧,您可以这样做,而不是同时检查两者if(stream_resolve_include_path($folder)!==false)。它的速度较慢,但一枪杀死了两只鸟。

另一种选择是简单地忽略E_WARNING而不是通过使用@mkdir(...);(因为这将简单地放弃所有可能的警告,不仅目录已经存在),而是在执行操作之前注册一个特定的错误处理程序:

namespace com\stackoverflow;

set_error_handler(function($errno, $errm) { 
    if (strpos($errm,"exists") === false) throw new \Exception($errm); //or better: create your own FolderCreationException class
});
mkdir($folder);
/* possibly more mkdir instructions, which is when this becomes useful */
restore_error_handler();


1

这是一个古老但仍是话题性的问题。只需使用is_dir()or file_exists()函数测试被测目录中.or ..文件的存在。每个目录必须包含以下文件:

is_dir("path_to_directory/.");    


0

检查路径是否为目录的方法可以如下:

function isDirectory($path) {
    $all = @scandir($path);
    return $all !== false;
}

注意:对于不存在的路径,它也将返回false,但对于UNIX / Windows则完美地工作

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.