Come posso verificare se esiste una directory? "Is_dir", "file_exists" o entrambi?


329

Voglio creare una directory se non esiste già.

Usi is_dirabbastanza per quello scopo?

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

O dovrei combinare is_dircon file_exists?

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

3
L'operatore booleano OR dovrebbe essere AND, e in PHP è scritto come &&
Ivo Renkema

15
@IvoRenkema PHP supporta anche or/ andoltre ||/ &&.
Camilo Martin,

1
L'operatore non &&è utile qui, perché, se il file non esiste ( !file_exists($dir) == true), sicuramente non è una directory. E se il file esiste, !is_dir($dir)non verrà controllato, perché !file_exists($dir)tornerà falsee l' &&operatore è in corto circuito .
Boolean_Type

4
A mio avviso, l'operatore dovrebbe essere OR.
Mojtaba,

con && funziona perfettamente per me
FABBRj

Risposte:


220

Entrambi tornerebbero veri sui sistemi Unix: in Unix tutto è un file, comprese le directory. Ma per verificare se quel nome è stato preso, dovresti controllare entrambi. Potrebbe esserci un normale file chiamato "foo", che ti impedirebbe di creare un nome di directory "foo".


37
non dimenticare di verificare se is_writable anche
Drewdin

10
@Drewdin per cui vorresti controllare il genitore is_writable, vero?
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.";
}

46
Molto quello che dice l'eco ...
Kay - SE è malvagio il

13
considerando che accetta l'input post e lo usa così com'è, inoltre rende 0777 dir, quindi non è affatto sicuro; P
sEver

2
Più seriamente, $ dirname potrebbe essere disinfettato e l'autorizzazione potrebbe essere impostata su 0755. Aggiungete a ciò alcune direttive .htaccess. Ci sono altri consigli su 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
Quando usi mkdir- perché non hai semplicemente passato '$ nomefile'?
Howdy_McVedi

17

Penso che realpath () possa essere il modo migliore per convalidare se esiste un percorso http://www.php.net/realpath

Ecco una funzione di esempio:

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

Versione breve della stessa funzione

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

Esempi di output

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

uso

<?php

$folder = '/foo/bar';

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

mkdir($folder);
// Continue do stuff

2
Per chiunque si imbatta in questo, credo che realpath memorizzi nella cache le cartelle quando viene eseguito, quindi se viene eseguito una volta, la cartella viene rimossa dopo, potrebbe non restituire false se eseguita di nuovo.
Jase,

2
ma anche file_exist esiste
Sebas il

7

La seconda variante nel post delle domande non è corretta, poiché, se si dispone già di un file con lo stesso nome, ma non è una directory, !file_exists($dir)verrà restituita la falsecartella non verrà creata, pertanto si "failed to open stream: No such file or directory"verificherà un errore . In Windows c'è una differenza tra i tipi di 'file' e 'cartella', quindi è necessario utilizzare file_exists()e is_dir()allo stesso tempo, ad es .:

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
Puoi controllare il percorso completo e se non esiste crealo con mkdir ricorsivo: if (! File_exists ($ nome file2)) {mkdir ($ nome file2, 0777, vero); } Inoltre, il tuo codice non creerà mai il percorso completo se $ nomefile non esiste ...
Niels R.

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

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

3
L'impostazione di chmod 777 non è mai una buona idea. 755 è sufficiente per le cartelle.
Oldskool,

2

aggiungi true dopo 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.";
    }
     ?>

1

Bene, invece di controllare entrambi, potresti farlo if(stream_resolve_include_path($folder)!==false). È più lento ma uccide due uccelli in un colpo.

Un'altra opzione è semplicemente ignorare il E_WARNING, non usando @mkdir(...);(perché ciò semplicemente rinuncerebbe a tutti i possibili avvisi, non solo la directory ne esiste già una), ma registrando uno specifico gestore di errori prima di farlo:

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

Questa è una domanda vecchia, ma ancora attuale. Basta testare con la funzione is_dir()o file_exists()per la presenza del file .o ..nella directory sotto test. Ogni directory deve contenere questi file:

is_dir("path_to_directory/.");    

0

Questo è come lo faccio

if(is_dir("./folder/test"))
{
  echo "Exist";
}else{
  echo "Not exist";
}

Quando rispondi a una vecchia domanda, la tua risposta sarebbe molto più utile per gli altri utenti StackOverflow se includessi un contesto per spiegare come la tua risposta aiuta, in particolare per una domanda che ha già una risposta accettata. Vedi: Come scrivo una buona risposta .
David Buck,

0

Un modo per verificare se un percorso è directory può essere il seguente:

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

NOTA: restituirà false anche per percorsi inesistenti, ma funziona perfettamente per UNIX / Windows

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.