Как проверить, существует ли каталог с помощью PHP?


Я хочу создать каталог, если он не существует.

Достаточно ли для этой цели использования is_dir?

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

Или мне следует объединить is_dir с file_exists?

if (!file_exists($dir) && !is_dir($dir)) {
    mkdir($dir);         
} 
 262
php
Author: Axel, 2011-03-25

8 answers

Оба возвращали бы значение true в системах Unix - в Unix все является файлом, включая каталоги. Но чтобы проверить, занято ли это имя, вы должны проверить оба. Там может быть обычный файл с именем "foo", который помешает вам создать каталог с именем "foo".

 169
Author: Marc B, 2011-03-24 21:42:06
$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.";
}
 112
Author: Maher, 2013-05-22 15:43:07

Я думаю, что 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
 14
Author: inckie, 2015-03-09 03:43:20

Второй вариант, о котором идет речь, не подходит, потому что, если у вас уже есть файл с тем же именем, но он не является каталогом, !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);
}
 6
Author: Boolean_Type, 2016-03-08 09:46:11
$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);
}
 3
Author: rons, 2013-10-10 07:15:57
$save_folder = "some/path/" . date('dmy');

if (!file_exists($save_folder)) {
   mkdir($save_folder, 0777);
}
 1
Author: hour man, 2015-06-11 08:00:34

Ну, вместо того, чтобы проверять и то, и другое, вы могли бы сделать 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
Author: Sebas, 2017-05-23 10:31:34

Добавить true после 0777

<?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.";
    }
     ?>
 0
Author: Sujeet Kumar, 2018-03-10 08:11:42