Utwórz folder, jeśli jeszcze nie istnieje

642

W kilku instalacjach WordPress natknąłem się na Bluehost, gdzie napotkałem błędy w moim motywie WordPress, ponieważ folder przesyłania wp-content/uploadsnie był obecny.

Najwyraźniej instalator WordPress Bluehost cPanel nie tworzy tego folderu, choć HostGator tak.

Więc muszę dodać kod do mojego motywu, który sprawdza folder i tworzy go inaczej.

Scott B.
źródło
7
if (!file_exists('path/to/directory')) { mkdir('path/to/directory', 0777, true); }
Jestem najgłupszą osobą

Odpowiedzi:

1227

Spróbuj tego, używając mkdir :

if (!file_exists('path/to/directory')) {
    mkdir('path/to/directory', 0777, true);
}

Zauważ, że 0777jest to już domyślny tryb dla katalogów i może nadal być modyfikowany przez bieżący umask.

Gumbo
źródło
11
Brakowało ci flagi „rekurencyjnej” - patrz odpowiedź Satisha.
Francois Bourgeois
118
is_dir () jest nieco szybszy niż file_exists ()
pliashkou
43
@YuryPliashkou Może tak, ale to nie działa, jeśli istnieje już plik o tej nazwie.
Gumbo,
4
pytanie tutaj: więc jeśli w ścieżce / do znajdowałby się plik o nazwie „katalog”, to czy katalog_ zwróciłby wartość true, ale pliki_istniejące zwróciłyby wartość false?
Igor L.
8
file_exists- Sprawdza, czy plik lub katalog istnieje is_file- Mówi, czy nazwa pliku jest zwykłym plikiem is_dir- Mówi, czy nazwa pliku to katalog
TarranJones
137

Oto brakujący element. Musisz przekazać flagę „rekurencyjną” jako trzeci argument (boolean true) w wywołaniu mkdir w następujący sposób:

mkdir('path/to/directory', 0755, true);
Satish Gadhave
źródło
8
flaga „rekurencyjna” jest trzecim argumentem logicznymtrue
ahnbizcad
66

Coś bardziej uniwersalnego, ponieważ pojawia się w Google. Chociaż szczegóły są bardziej szczegółowe, tytuł tego pytania jest bardziej uniwersalny.

/** 
 * recursively create a long directory path
 */
function createPath($path) {
    if (is_dir($path)) return true;
    $prev_path = substr($path, 0, strrpos($path, '/', -2) + 1 );
    $return = createPath($prev_path);
    return ($return && is_writable($prev_path)) ? mkdir($path) : false;
}

To pójdzie ścieżką, być może z długim łańcuchem nie utworzonych katalogów, i przejdzie do następnego katalogu, aż dojdzie do istniejącego katalogu. Następnie spróbuje utworzyć następny katalog w tym katalogu i będzie kontynuował, aż utworzą wszystkie katalogi. Zwraca true, jeśli się powiedzie.

Można to poprawić, zapewniając poziom zatrzymania, aby po prostu zawiódł, jeśli wykracza poza folder użytkownika lub coś, i zawiera uprawnienia.

phazei
źródło
@phazei Otrzymuję wywołanie niezdefiniowanej funkcji z powodu wiersza $ return = createPath ($ prev_path);
Battousai
Dzięki @phazei :)
Alex
58

Co z taką funkcją pomocnika:

function makeDir($path)
{
     $ret = mkdir($path); // use @mkdir if you want to suppress warnings/errors
     return $ret === true || is_dir($path);
}

Zwróci, truejeśli katalog został pomyślnie utworzony lub już istnieje i falsejeśli nie można go utworzyć.

Lepszym rozwiązaniem jest to (nie powinny dawać żadnych ostrzeżeń):

function makeDir($path)
{
     return is_dir($path) || mkdir($path);
}
AndiDog
źródło
4
Jeśli usuniesz @i is_dirzastąpisz go odpowiednim sprawdzeniem, moja opinia jest Twoja :) Punkty bonusowe za sprawdzenie, czy katalog nadrzędny is_writable()dla wodoszczelnej funkcji pomocnika.
Pekka
Użycie @ w celu stłumienia błędów jest hitem wydajności. Lepiej sprawdzić, czy już nie istnieje jak Gumbo
Simon
1
Niezależnie od eliminacji błędów, jestem skłonny do -1 w pierwszym przykładzie. Drugi jest o tyle lepszy, że pierwszy jest bezcelowy.
Justin Johnson
Trudno jest odczytać kod tylko dlatego, że umieszcza się go w 1 linii. Przyjęta odpowiedź jest znacznie jaśniejsza.
MikeKulls,
26

Szybszy sposób na utworzenie folderu:

if (!is_dir('path/to/directory')) {
    mkdir('path/to/directory', 0777, true);
}
Elyor
źródło
Dałoby to błąd, jeśli w tej ścieżce znajduje się plik o nazwie „katalog”.
Guney Ozsan
23

Rekurencyjnie utwórz ścieżkę do katalogu:

function makedirs($dirpath, $mode=0777) {
    return is_dir($dirpath) || mkdir($dirpath, $mode, true);
}

Inspirowany Pythonem os.makedirs()

użytkownik
źródło
11

W WordPress istnieje również bardzo przydatna funkcja wp_mkdir_p która rekurencyjnie tworzy strukturę katalogów.

Źródło w celach informacyjnych: -

function wp_mkdir_p( $target ) {
    $wrapper = null;

    // strip the protocol
    if( wp_is_stream( $target ) ) {
        list( $wrapper, $target ) = explode( '://', $target, 2 );
    }

    // from php.net/mkdir user contributed notes
    $target = str_replace( '//', '/', $target );

    // put the wrapper back on the target
    if( $wrapper !== null ) {
        $target = $wrapper . '://' . $target;
    }

    // safe mode fails with a trailing slash under certain PHP versions.
    $target = rtrim($target, '/'); // Use rtrim() instead of untrailingslashit to avoid formatting.php dependency.
    if ( empty($target) )
        $target = '/';

    if ( file_exists( $target ) )
        return @is_dir( $target );

    // We need to find the permissions of the parent folder that exists and inherit that.
    $target_parent = dirname( $target );
    while ( '.' != $target_parent && ! is_dir( $target_parent ) ) {
        $target_parent = dirname( $target_parent );
    }

    // Get the permission bits.
    if ( $stat = @stat( $target_parent ) ) {
        $dir_perms = $stat['mode'] & 0007777;
    } else {
        $dir_perms = 0777;
    }

    if ( @mkdir( $target, $dir_perms, true ) ) {

        // If a umask is set that modifies $dir_perms, we'll have to re-set the $dir_perms correctly with chmod()
        if ( $dir_perms != ( $dir_perms & ~umask() ) ) {
            $folder_parts = explode( '/', substr( $target, strlen( $target_parent ) + 1 ) );
            for ( $i = 1; $i <= count( $folder_parts ); $i++ ) {
                @chmod( $target_parent . '/' . implode( '/', array_slice( $folder_parts, 0, $i ) ), $dir_perms );
            }
        }

        return true;
    }

    return false;
}
Trevor Mills
źródło
6

Potrzebuję tego samego dla strony logowania. Musiałem stworzyć katalog z dwiema zmiennymi. Katalog $ to główny folder, w którym chciałem utworzyć inny podfolder z numerem licencji użytkownika.

include_once("../include/session.php");
$lnum = $session->lnum; //Users license number from sessions
$directory = uploaded_labels; // Name of directory that folder is being created in

if (!file_exists($directory."/".$lnum)) {
mkdir($directory."/".$lnum, 0777, true);
}
Progrower
źródło
5

To jest najbardziej aktualne rozwiązanie bez tłumienia błędów:

if (!is_dir('path/to/directory')) {
    mkdir('path/to/directory');
}
Andreas
źródło
3

Jeśli chcesz uniknąć problemu file_existsVS is_dir, radzę zajrzeć tutaj

Próbowałem tego i tworzy katalog tylko wtedy, gdy katalog nie istnieje . Nie obchodzi go to, że istnieje plik o tej nazwie.

/* Creates the directory if it does not exist */
$path_to_directory = 'path/to/directory';
if (!file_exists($path_to_directory) && !is_dir($path_to_directory)) {
    mkdir($path_to_directory, 0777, true);
}
joaorodr84
źródło
2
if (!is_dir('path_directory')) {
    @mkdir('path_directory');
}
Mayur Kukadiya
źródło
3
Eliminacja błędów? Dlaczego?
canadiancreed
4
Dzięki eliminacji błędów nie ma potrzeby sprawdzania, czy katalog istnieje
neoascetic
4
lepiej radzić sobie z błędami niż je pomijać. Jeśli to się nie powiedzie, nigdy nie dowiesz się, dlaczego, i będziesz musiał to zbadać
Tim Ogilvy,
W wysoce współbieżnych / wielowątkowych środowiskach zaleca się wyeliminowanie błędu. Może wystąpić sytuacja wyścigu, w której dwa lub więcej wątków oceni is_dir () na false i spróbuje utworzyć katalog. Pierwszy wątek będzie mógł go utworzyć bez problemu, ale inne wątki tego nie zrobią, ponieważ katalog już istnieje. Aby uniknąć pominięcia faktycznie nieudanego tworzenia katalogu, powinieneś ponownie sprawdzić istnienie katalogu po wywołaniu @mkdir ().
tobain
2

Możesz spróbować również:

$dirpath = "path/to/dir";
$mode = "0777";
is_dir($dirpath) || mkdir($dirpath, $mode, true);
simhumileco
źródło
2

Aby utworzyć folder, jeśli jeszcze nie istnieje

Biorąc pod uwagę środowisko pytania.

  • WordPress.
  • Serwer WWW.
  • Zakładając, że jego Linux nie jest systemem Windows z uruchomionym PHP.

I cytowanie z: http://php.net/manual/en/function.mkdir.php

bool mkdir (string $ pathname [, int $ mode = 0777 [, bool $ recursive = FALSE [, $ $ kontekst]]])

Instrukcja mówi, że jedynym wymaganym parametrem jest $pathname!

więc możemy po prostu kodować:

<?php
error_reporting(0); 
if(!mkdir('wp-content/uploads')){
   // todo
}
?>

Wyjaśnienie:

Nie musimy przekazywać żadnego parametru ani sprawdzać, czy folder istnieje, ani nawet parametru trybu przejścia, chyba że jest to konieczne; z następujących powodów:

  • Polecenie utworzy folder z uprawnieniem 0755 (domyślne uprawnienie do współdzielonego folderu hostingowego) lub 0777 domyślnym poleceniem.
  • modejest ignorowany na Windows Hosting z PHP .
  • Już mkdirkomenda posiada wbudowany w sprawdzający czy folder istnieje; więc musimy sprawdzić zwrot tylko True | False; i to nie jest błąd, to tylko ostrzeżenie, a Ostrzeżenie jest domyślnie wyłączone na serwerach hostingowych.
  • Zgodnie z prędkością jest to szybsze, jeśli ostrzeżenie jest wyłączone.

To tylko kolejny sposób, aby spojrzeć na pytanie i nie domagać się lepszego lub najbardziej optymalnego rozwiązania.

Testowane na PHP7, Production Server, Linux

WPDev
źródło
2
$upload = wp_upload_dir();
$upload_dir = $upload['basedir'];
$upload_dir = $upload_dir . '/newfolder';
if (! is_dir($upload_dir)) {
   mkdir( $upload_dir, 0700 );
}
Nikunj Kathrotiya
źródło
2

Powinniśmy zawsze modulować nasz kod, a ja napisałem to samo sprawdź go poniżej ... Najpierw sprawdzamy katalog, jeśli go nie ma, tworzymy katalog.

$boolDirPresents = $this->CheckDir($DirectoryName);

if (!$boolDirPresents) {
        $boolCreateDirectory = $this->CreateDirectory($DirectoryName);
        if ($boolCreateDirectory) {
        echo "Created successfully";
      }
  }

function CheckDir($DirName) {
    if (file_exists($DirName)) {
        echo "Dir Exists<br>";
        return true;
    } else {
        echo "Dir Not Absent<br>";
        return false;
    }
}

function CreateDirectory($DirName) {
    if (mkdir($DirName, 0777)) {
        return true;
    } else {
        return false;
    }
}
Aditya
źródło
1

Najpierw musisz sprawdzić, czy katalog istnieje file_exists('path_to_directory')

Następnie użyj, mkdir(path_to_directory)aby utworzyć katalog

mkdir( string $pathname [, int $mode = 0777 [, bool $recursive = FALSE [, resource $context ]]] ) : bool

Więcej informacji o mkdir () tutaj

Pełny kod tutaj:

$structure = './depth1/depth2/depth3/';
if (!file_exists($structure)) {
    mkdir($structure);
}
Nasir Khan
źródło
0

Proszę bardzo.

if (!is_dir('path/to/directory')) {
    if (!mkdir('path/to/directory', 0777, true) && !is_dir('path/to/directory')) {
        throw new \RuntimeException(sprintf('Directory "%s" was not created', 'path/to/directory'));
    }
}
ULIDU THEERAKE
źródło
PHPStorm (z inspekcjami PHP) daje dokładnie taką sugestię ;-) btw. możesz połączyć zewnętrzne, jeśli w wewnętrzne: if (! is_dir (...) &&! mkdir (...) &&! is_dir (...)) ...
aProgger
-1

Przyjęta odpowiedź działa, ale ze względu na uprawnienia nie jest to właściwe rozwiązanie. Uprawnienia 0777 umożliwiają każdemu dostęp do / odczyt / zapis katalogu. Nie tego chcemy dla katalogu wysyłania na serwerze internetowym. Oto sugerowane prawidłowe i kompletne rozwiązanie.

$path_to_directory = 'path/to/directory';
if (!file_exists($path_to_directory) && !is_dir($path_to_directory)) {
    mkdir($path_to_directory, 0644, true);
}

0644 są odpowiednimi uprawnieniami do katalogu uploads, ponieważ zazwyczaj nie chcemy, aby przesyłano go na serwer, aby tam był wykonywany.

true to trzeci parametr służący do ustawiania właściwości rekurencyjnej na true lub false. Pozwala na tworzenie zagnieżdżonych katalogów określonych w nazwie ścieżki.

Umair Anwar
źródło