Comment vérifier si un répertoire existe? "Is_dir", "file_exists" ou les deux?

329

Je veux créer un répertoire s'il n'existe pas déjà.

Utilise-t-il is_dirsuffisamment à cette fin?

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

Ou dois-je combiner is_diravec file_exists?

if ( !file_exists( $dir ) && !is_dir( $dir ) ) {
    mkdir( $dir );       
} 
Peter
la source
3
L'opérateur booléen OR doit être AND, et en PHP, il est écrit comme &&
Ivo Renkema
15
@IvoRenkema PHP prend également en charge or/ andoutre ||/ &&.
Camilo Martin
1
L'opérateur &&est inutile ici, car, si le fichier n'existe pas ( !file_exists($dir) == true), ce n'est certainement pas un répertoire. Et si le fichier existe, !is_dir($dir)ne sera pas vérifié, car !file_exists($dir)reviendra falseet l' &&opérateur est en court-circuit .
Boolean_Type
4
À mon avis, l'opérateur devrait être OU.
Mojtaba
avec && cela fonctionne parfaitement pour moi
FABBRj

Réponses:

220

Les deux reviendraient vrai sur les systèmes Unix - sous Unix, tout est un fichier, y compris les répertoires. Mais pour tester si ce nom est pris, vous devez vérifier les deux. Il pourrait y avoir un fichier normal nommé 'foo', qui vous empêcherait de créer un nom de répertoire 'foo'.

Marc B
la source
37
n'oubliez pas de vérifier si is_writable également
Drewdin
10
@Drewdin vous voudriez vérifier le parent is_writablen'est-ce pas?
Matthew Scharley
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.";
}
Maher
la source
46
Très bien ce que dit l'écho…
kay - SE is evil
13
étant donné qu'il prend une entrée de post et l'utilise telle quelle, plus 0777 dir, ce n'est pas du tout sûr; P
sEver
2
Plus sérieusement, $ dirname pourrait être nettoyé et l'autorisation pourrait être définie sur 0755. Ajoutez à cela quelques directives .htaccess. Il y a d'autres recommandations sur 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
Lorsque vous utilisez mkdir- pourquoi n'avez-vous pas simplement passé «$ filename»?
Howdy_McGee
17

Je pense que realpath () peut être le meilleur moyen de valider si un chemin existe http://www.php.net/realpath

Voici un exemple de fonction:

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

Version courte de la même fonction

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

Exemples de sortie

<?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) "/"

Usage

<?php

$folder = '/foo/bar';

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

mkdir($folder);
// Continue do stuff
inckie
la source
2
Pour tous ceux qui rencontrent cela, je crois que realpath met en cache les dossiers lorsqu'il s'exécute, donc s'il est exécuté une fois, le dossier est supprimé après cela, il peut ne pas retourner false s'il est exécuté à nouveau.
Jase
2
file_exists cependant
Sebas
7

La deuxième variante dans le message en question n'est pas correcte, car si vous avez déjà un fichier du même nom, mais que ce n'est pas un répertoire, !file_exists($dir)reviendra false, le dossier ne sera pas créé, donc une erreur se "failed to open stream: No such file or directory"produira. Sous Windows, il existe une différence entre les types de «fichier» et de «dossier», il faut donc utiliser file_exists()et is_dir()en même temps, par exemple:

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);
}
Boolean_Type
la source
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);
}
rons
la source
1
Vous pouvez vérifier le chemin complet et s'il n'existe pas, créez-le avec mkdir récursif: if (! File_exists ($ filename2)) {mkdir ($ filename2, 0777, true); } De plus, votre code ne créera jamais le chemin complet si $ filename n'existe pas ...
Niels R.
3
$save_folder = "some/path/" . date('dmy');

if (!file_exists($save_folder)) {
   mkdir($save_folder, 0777);
}
homme d'heure
la source
3
La configuration de chmod 777 n'est jamais une bonne idée. 755 est suffisant pour les dossiers.
Oldskool
2

ajouter vrai après 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.";
    }
     ?>
Sujeet Kumar
la source
1

Eh bien, au lieu de vérifier les deux, vous pourriez le faire if(stream_resolve_include_path($folder)!==false). Il est plus lent mais tue deux oiseaux d'un coup.

Une autre option consiste à simplement ignorer le E_WARNING, non pas en utilisant @mkdir(...);(car cela annulerait simplement tous les avertissements possibles, non seulement le répertoire existe déjà), mais en enregistrant un gestionnaire d'erreurs spécifique avant de le faire:

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();
Sebas
la source
1

Il s'agit d'une question ancienne, mais toujours d'actualité. Testez simplement avec la fonction is_dir()ou file_exists()la présence du fichier .ou ..dans le répertoire sous test. Chaque répertoire doit contenir ces fichiers:

is_dir("path_to_directory/.");    
djordje
la source
0

C'est comme ça que je fais

if(is_dir("./folder/test"))
{
  echo "Exist";
}else{
  echo "Not exist";
}
Jetro Bernardo
la source
Lorsque vous répondez à une ancienne question, votre réponse serait beaucoup plus utile aux autres utilisateurs de StackOverflow si vous incluez un contexte pour expliquer comment votre réponse aide, en particulier pour une question qui a déjà une réponse acceptée. Voir: Comment écrire une bonne réponse .
David Buck
0

Un moyen de vérifier si un chemin est un répertoire peut être le suivant:

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

REMARQUE: Il renverra également false pour un chemin inexistant, mais fonctionne parfaitement pour UNIX / Windows

Máxima Alekz
la source