Como verifico se existe um diretório? "Is_dir", "file_exists" ou ambos?

329

Quero criar um diretório se ele já não existir.

Está usando o is_dirsuficiente para esse fim?

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

Ou devo combinar is_dircom file_exists?

if ( !file_exists( $dir ) && !is_dir( $dir ) ) {
    mkdir( $dir );       
} 
Peter
fonte
3
O operador booleano OR deve ser e, em PHP é escrito como &&
Ivo Renkema
15
@IvoRenkema O PHP também suporta or/ andalém de ||/ &&.
Camilo Martin
1
O operador &&é inútil aqui, porque, se o arquivo não existir ( !file_exists($dir) == true), com certeza não é um diretório. E se o arquivo existir, !is_dir($dir)não será verificado, pois !file_exists($dir)retornará falsee o &&operador está em curto-circuito .
Boolean_Type
4
Na minha opinião, o operador deve ser OR.
Mojtaba
com && isso funciona perfeitamente para mim
FABBRj 04/02

Respostas:

220

Ambos retornariam verdadeiros nos sistemas Unix - no Unix tudo é um arquivo, incluindo diretórios. Mas, para testar se esse nome foi escolhido, verifique os dois. Pode haver um arquivo comum chamado 'foo', o que impediria a criação de um nome de diretório 'foo'.

Marc B
fonte
37
Não se esqueça de verificar se is_writable também
Drewdin
10
@Drewdin você gostaria de verificar os pais is_writable, não é?
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
fonte
46
Muito o que o eco diz ...
kay - SE é mau
13
considerando que leva insumos pós e usa-lo como está, mais faz 0777 dir, prolly não que seguro em tudo; P
Sever
2
Mais seriamente, $ dirname pode ser limpo e a permissão pode ser definida como 0755. Adicione a isso algumas diretivas .htaccess. Há algumas outras recomendações sobre a 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 você usa mkdir- por que você não passou '$ filename'?
precisa saber é o seguinte
17

Eu acho que realpath () pode ser a melhor maneira de validar se existe um caminho http://www.php.net/realpath

Aqui está um exemplo de função:

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

Versão curta da mesma função

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

Exemplos de saída

<?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
inckie
fonte
2
Para quem se deparar com isso, acredito que o realpath armazena em cache as pastas quando é executado; portanto, se for executado uma vez, a pasta será removida depois disso e poderá não retornar falso se for executado novamente.
Jase
2
o que acontece com file_exists embora
Sebas
7

A segunda variante na postagem da pergunta não está ok, porque, se você já possui um arquivo com o mesmo nome, mas não é um diretório, !file_exists($dir)retornará false, a pasta não será criada e, portanto, "failed to open stream: No such file or directory"ocorrerá um erro . No Windows, há uma diferença entre os tipos 'arquivo' e 'pasta'; portanto, é necessário usar file_exists()e is_dir()ao mesmo tempo, por exemplo:

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
fonte
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
fonte
1
Você pode verificar o caminho completo e, se ele não existir, criá-lo com mkdir recursivo: if (! File_exists ($ filename2)) {mkdir ($ filename2, 0777, true); } Além disso, seu código nunca criará o caminho completo se não existir $ filename ...
Niels R. -
3
$save_folder = "some/path/" . date('dmy');

if (!file_exists($save_folder)) {
   mkdir($save_folder, 0777);
}
homem hora
fonte
3
Definir o chmod 777 nunca é uma boa ideia. 755 é suficiente para pastas.
precisa
2

adicionar true apó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
fonte
1

Bem, em vez de verificar os dois, você poderia fazer if(stream_resolve_include_path($folder)!==false). É mais lento, mas mata dois coelhos de uma só vez.

Outra opção é simplesmente ignorar o E_WARNING, não usando @mkdir(...);(porque isso simplesmente dispensaria todos os avisos possíveis, não apenas o diretório já existe), mas registrando um manipulador de erro específico antes de fazê-lo:

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

Esta é uma pergunta antiga, mas ainda atual. Apenas teste com a função is_dir()ou file_exists()a presença do arquivo .ou ..no diretório em teste. Cada diretório deve conter estes arquivos:

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

É assim que eu faço

if(is_dir("./folder/test"))
{
  echo "Exist";
}else{
  echo "Not exist";
}
Jetro Bernardo
fonte
Ao responder a uma pergunta antiga, sua resposta seria muito mais útil para outros usuários do StackOverflow se você incluísse algum contexto para explicar como sua resposta ajuda, principalmente para uma pergunta que já tenha uma resposta aceita. Veja: Como escrevo uma boa resposta .
David Buck
0

Uma maneira de verificar se um caminho é diretório pode ser a seguir:

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

NOTA: Ele retornará false também para o caminho inexistente, mas funciona perfeitamente para UNIX / Windows

Máxima Alekz
fonte