Jak sprawdzić, czy istnieje katalog? „Is_dir”, „file_exists” czy oba?


329

Chcę utworzyć katalog, jeśli jeszcze nie istnieje.

Czy is_dirwystarczy użyć do tego celu?

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

Czy mam połączyć is_dirz file_exists?

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

3
Operator logiczny OR powinien być AND, aw PHP jest napisany jako &&
Ivo Renkema

15
@IvoRenkema PHP obsługuje również or/ andoprócz ||/ &&.
Camilo Martin,

1
Operator nie &&jest tu przydatny, ponieważ jeśli plik nie istnieje ( !file_exists($dir) == true), na pewno nie jest to katalog. A jeśli plik istnieje, !is_dir($dir)nie zostanie sprawdzony, ponieważ !file_exists($dir)powróci, falsea &&operator jest zwarty .
Boolean_Type

4
Moim zdaniem operatorem powinien być OR.
Mojtaba

z && to działa idealnie dla mnie
FABBRj

Odpowiedzi:


220

Oba zwrócą prawdę w systemach uniksowych - w Unixie wszystko jest plikiem, w tym katalogami. Ale aby sprawdzić, czy ta nazwa jest zajęta, sprawdź oba. Może istnieć zwykły plik o nazwie „foo”, który uniemożliwiłby utworzenie katalogu o nazwie „foo”.


37
nie zapomnij sprawdzić, czy is_writable również
Drewdin

10
@Drewdin, czy chcesz sprawdzić rodzica is_writable, prawda?
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
Bardzo to, co mówi echo…
Kay - SE jest złe

13
biorąc pod uwagę, że wymaga on wprowadzenia danych i używa go w stanie, w jakim się znajduje, plus sprawia, że ​​0777 dir, wcale nie jest wcale taki bezpieczny; P
sver

2
Co więcej, $ dirname może zostać zdezynfekowane, a uprawnienia można ustawić na 0755. Dodaj do tego kilka dyrektyw .htaccess. Istnieje kilka dalszych zaleceń na 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
Kiedy używasz mkdir- dlaczego nie przekazałeś po prostu „$ filename”?
Howdy_McGee

17

Myślę, że realpath () może być najlepszym sposobem na sprawdzenie poprawności, jeśli istnieje ścieżka http://www.php.net/realpath

Oto przykładowa funkcja:

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

Krótka wersja tej samej funkcji

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

Przykłady wyników

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

Stosowanie

<?php

$folder = '/foo/bar';

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

mkdir($folder);
// Continue do stuff

2
Dla każdego, kto się z tym zetknie, uważam, że realpath buforuje foldery podczas uruchamiania, więc jeśli zostanie uruchomiony raz, to folder zostanie usunięty, może nie zwrócić wartości false, jeśli zostanie uruchomiony ponownie.
Jase

2
podobnie jak file_exists
Sebas

7

Drugi wariant kwestionowanego postu nie jest w porządku, ponieważ jeśli masz już plik o tej samej nazwie, ale nie jest to katalog, !file_exists($dir)wróci false, folder nie zostanie utworzony, więc "failed to open stream: No such file or directory"wystąpi błąd . W systemie Windows istnieje różnica między typami „plików” i „folderów”, więc należy używać file_exists()i is_dir()jednocześnie, na przykład:

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
Możesz sprawdzić pełną ścieżkę, a jeśli nie istnieje, utwórz ją za pomocą rekurencyjnego programu mkdir: if (! File_exists ($ filename2)) {mkdir ($ filename2, 0777, true); } Poza tym kod nigdy nie utworzy pełnej ścieżki, jeśli nazwa pliku $ nie istnieje ...
Niels R.

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

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

3
Ustawienie chmod 777 nigdy nie jest dobrym pomysłem. 755 jest wystarczające dla folderów.
Oldskool,

2

dodaj true po 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

Zamiast sprawdzać oba, możesz to zrobić if(stream_resolve_include_path($folder)!==false). Jest wolniejszy, ale zabija dwa ptaki jednym strzałem.

Inną opcją jest po prostu zignorowanie E_WARNING, nie za pomocą @mkdir(...);(ponieważ po prostu zrezygnuje ze wszystkich możliwych ostrzeżeń, nie tylko katalog już istnieje), ale przez zarejestrowanie określonej procedury obsługi błędów:

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

To stare, ale wciąż aktualne pytanie. Wystarczy przetestować za pomocą funkcji is_dir()lub file_exists()obecność pliku .lub ..w testowanym katalogu. Każdy katalog musi zawierać następujące pliki:

is_dir("path_to_directory/.");    

0

Tak właśnie robię

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

Odpowiadając na stare pytanie, twoja odpowiedź byłaby o wiele bardziej przydatna dla innych użytkowników StackOverflow, jeśli podasz kontekst, w którym wyjaśnisz, w jaki sposób twoja odpowiedź pomaga, szczególnie w przypadku pytania, które ma już zaakceptowaną odpowiedź. Zobacz: Jak napisać dobrą odpowiedź .
David Buck

0

Sposób sprawdzenia, czy ścieżka to katalog, może być następujący:

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

UWAGA: Zwróci wartość false dla nieistniejącej ścieżki, ale działa idealnie w systemach UNIX / Windows

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.