¿Cómo verifico si existe un directorio? "Is_dir", "file_exists" o ambos?

329

Quiero crear un directorio si aún no existe.

¿Está usando lo is_dirsuficiente para ese propósito?

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

¿O debería combinar is_dircon file_exists?

if ( !file_exists( $dir ) && !is_dir( $dir ) ) {
    mkdir( $dir );       
} 
Peter
fuente
3
El operador booleano OR debería ser AND, y en PHP se escribe como &&
Ivo Renkema
15
@IvoRenkema PHP también es compatible con or/ andademás de ||/ &&.
Camilo Martin
1
El operador no &&es útil aquí, porque, si el archivo no existe ( !file_exists($dir) == true), seguro que no es un directorio. Y si el archivo existe, !is_dir($dir)no se verificará, porque !file_exists($dir)volverá falsey el &&operador está en cortocircuito .
Boolean_Type
44
En mi opinión, el operador debería ser OR.
Mojtaba
con && esto funciona perfectamente para mí
FABBRj

Respuestas:

220

Ambos serían verdaderos en los sistemas Unix: en Unix todo es un archivo, incluidos los directorios. Pero para probar si se toma ese nombre, debe verificar ambos. Puede haber un archivo normal llamado 'foo', que evitaría que cree un nombre de directorio 'foo'.

Marc B
fuente
37
no te olvides de comprobar si también se puede
escribir
10
@Drewdin, ¿querrías consultar a los padres para saberlo is_writable?
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
fuente
46
Mucho de lo que dice el eco ...
kay - SE es malvado
13
teniendo en cuenta que toma la entrada posterior y la usa tal cual, además hace 0777 dir, probablemente no es tan seguro en absoluto; P
sEver
2
Más en serio, $ dirname podría desinfectarse y el permiso podría establecerse en 0755. Agregue a eso algunas directivas .htaccess. Hay más recomendaciones en 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.
77
Cuando lo usas mkdir, ¿por qué no pasaste '$ filename'?
Howdy_McGee
17

Creo que realpath () puede ser la mejor manera de validar si existe una ruta http://www.php.net/realpath

Aquí hay una función de ejemplo:

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

Versión corta de la misma función.

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

Ejemplos de salida

<?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
chiflado
fuente
2
Para cualquiera que se encuentre con esto, creo que Realpath almacena en caché las carpetas cuando se ejecuta, por lo que si se ejecuta una vez, la carpeta se elimina después de eso, es posible que no devuelva falso si se ejecuta nuevamente.
Jase
2
aunque file_exists aunque
Sebas
7

La segunda variante en la publicación de preguntas no está bien, porque, si ya tiene un archivo con el mismo nombre, pero no es un directorio, !file_exists($dir)volverá false, no se creará la carpeta, por lo que se "failed to open stream: No such file or directory"producirá un error . En Windows hay una diferencia entre los tipos de 'archivo' y 'carpeta', por lo que debe usar file_exists()y, is_dir()al mismo tiempo, por ejemplo:

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
fuente
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
fuente
1
Puede verificar la ruta completa y, si no existe, crearla con mkdir recursivo: if (! File_exists ($ filename2)) {mkdir ($ filename2, 0777, true); } Además, su código nunca creará la ruta completa si $ filename no existe ...
Niels R.
3
$save_folder = "some/path/" . date('dmy');

if (!file_exists($save_folder)) {
   mkdir($save_folder, 0777);
}
hora hombre
fuente
3
Configurar chmod 777 nunca es una buena idea. 755 es suficiente para carpetas.
Oldskool
2

agregar verdadero después de 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
fuente
1

Bueno, en lugar de verificar ambos, podrías hacerlo if(stream_resolve_include_path($folder)!==false). Es más lento pero mata a dos pájaros de un tiro.

Otra opción es simplemente ignorar E_WARNING, no mediante el uso @mkdir(...);(porque eso simplemente anularía todas las advertencias posibles, no solo el directorio ya existe), sino registrando un controlador de errores específico antes de hacerlo:

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
fuente
1

Esta es una pregunta vieja, pero aún tópica. Simplemente pruebe con la función is_dir()o file_exists()la presencia del archivo .o ..en el directorio bajo prueba. Cada directorio debe contener estos archivos:

is_dir("path_to_directory/.");    
djordje
fuente
0

Así es como lo hago

if(is_dir("./folder/test"))
{
  echo "Exist";
}else{
  echo "Not exist";
}
Jetro Bernardo
fuente
Al responder una pregunta anterior, su respuesta sería mucho más útil para otros usuarios de StackOverflow si incluyera algún contexto para explicar cómo ayuda su respuesta, particularmente para una pregunta que ya tiene una respuesta aceptada. Ver: ¿Cómo escribo una buena respuesta ?
David Buck el
0

Una forma de verificar si una ruta es directorio puede ser la siguiente:

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

NOTA: también devolverá falso para la ruta no existente, pero funciona perfectamente para UNIX / Windows

Máxima Alekz
fuente