Создать папку, если она еще не существует


641

Я столкнулся с несколькими случаями установки WordPress с Bluehost, где я столкнулся с ошибками в моей теме WordPress, потому что папка загрузкиwp-content/uploads отсутствовала.

Очевидно, установщик Bluehost cPanel WordPress не создает эту папку, хотя HostGator делает.

Поэтому мне нужно добавить код в мою тему, который проверяет папку и создает ее в противном случае.


7
if (!file_exists('path/to/directory')) { mkdir('path/to/directory', 0777, true); }
Я самый глупый человек

Ответы:


1228

Попробуйте это, используя mkdir :

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

Обратите внимание, что 0777это уже режим по умолчанию для каталогов, и он все еще может быть изменен текущим значением umask.


11
Вы пропустили «рекурсивный» флаг - смотрите ответ Сатиша.
Франсуа Буржуа

118
is_dir () немного быстрее, чем file_exists ()
pliashkou

43
@YuryPliashkou Да, может быть, но это не сработает, если уже есть файл с таким именем.
Гамбо

4
вопрос здесь: так что если в path / to будет файл с именем 'directory', is_dir вернет true, а file_exists вернет false?
Игорь Львович

8
file_exists- Проверяет, существует ли файл или каталог is_file- Сообщает, является ли имя файла обычным файлом is_dir- Указывает, является ли имя файла каталогом
TarranJones

137

Вот недостающий кусок. Вам нужно передать флаг 'recursive' в качестве третьего аргумента (логическое true) в вызове mkdir следующим образом:

mkdir('path/to/directory', 0755, true);

8
«рекурсивный» флаг является логическим третьим аргументомtrue
ahnbizcad

66

Что-то более универсальное, так как это появляется в Google. Хотя детали более конкретны, название этого вопроса более универсально.

/** 
 * 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;
}

Это займет путь, возможно, с длинной цепочкой несозданных каталогов, и будет идти вверх по одному каталогу, пока он не попадет в существующий каталог. Затем он попытается создать следующий каталог в этом каталоге и продолжит, пока не будут созданы все каталоги. Возвращает истину, если успешно.

Может быть улучшен путем предоставления уровня остановки, так что он просто терпит неудачу, если он выходит за пределы пользовательской папки или чего-то еще, и путем включения разрешений.


@phazei Я получаю вызов неопределенной функции из-за строки $ return = createPath ($ prev_path);
Баттосай

Спасибо @phazei :)
Алекс

58

Как насчет вспомогательной функции, подобной этой:

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

Он вернется, trueесли каталог был успешно создан или уже существует, и falseесли каталог не может быть создан.

Лучше альтернатива этому (не должны давать никаких предупреждений):

function makeDir($path)
{
     return is_dir($path) || mkdir($path);
}

4
Если вы удалите @и замените его надлежащей is_dirпроверкой, мое повышение будет вашим :) Бонусные баллы за проверку того, является ли родительский каталог is_writable()водонепроницаемой вспомогательной функцией.
Пекка

Использование @ для подавления ошибок снижает производительность. Лучше проверить, что он еще не существует, как Гамбо
Саймон

1
Независимо от подавления ошибок, я склонен к -1 для первого примера. Второе намного лучше, чем первое бессмысленно.
Джастин Джонсон

Это трудно читать код только для того, чтобы поместить его в 1 строку. Принятый ответ гораздо понятнее.
MikeKulls

27

Более быстрый способ создания папки:

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

Это даст ошибку, если по этому пути будет файл с именем «каталог».
Гуней Озсан


11

В WordPress есть также очень удобная функция wp_mkdir_p. которая будет рекурсивно создавать структуру каталогов.

Источник для справки: -

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

6

Мне нужно то же самое для входа на сайт. Мне нужно было создать каталог с двумя переменными. Каталог $ - это основная папка, в которой я хотел создать другую подпапку с номером лицензии пользователя.

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

5

Это самое современное решение без подавления ошибок:

if (!is_dir('path/to/directory')) {
    mkdir('path/to/directory');
}

3

Если вы хотите избежать проблемы с file_existsVS is_dir, я бы посоветовал вам посмотреть здесь

Я попробовал это, и он только создает каталог, если каталог не существует . Ему все равно, есть ли файл с таким именем.

/* 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);
}

2
if (!is_dir('path_directory')) {
    @mkdir('path_directory');
}

3
Подавление ошибок? Почему?
canadiancreed

4
При подавлении ошибок нет необходимости проверять, существует ли каталог
neoascetic

4
Лучше обрабатывать ошибки, чем подавлять их. Если это не удастся, вы никогда не узнаете почему, и вам придется исследовать это
Тим Огилви

В высокопараллельных / многопоточных средах желательно подавлять ошибку. Может возникнуть состояние гонки, при котором два или более потоков оценят is_dir () как false и попытаются создать каталог. Первый поток сможет создать его без каких-либо проблем, но другие потоки не смогут этого сделать, поскольку каталог уже существует. Чтобы не пропустить фактически неудачное создание каталога, вы должны проверить существование каталога после повторного вызова @mkdir ().
17

2

Вы также можете попробовать:

$dirpath = "path/to/dir";
$mode = "0777";
is_dir($dirpath) || mkdir($dirpath, $mode, true);

2

Создать папку, если она еще не существует

Учитывая вопрос среды.

  • WordPress.
  • Сервер веб-хостинга.
  • Предполагая, что его Linux не Windows, работает PHP.

И цитирование: http://php.net/manual/en/function.mkdir.php

bool mkdir (строка $ pathname [, int $ mode = 0777 [, bool $ recursive = FALSE [, ресурс $ context]]])

Руководство говорит, что единственным обязательным параметром является $pathname!

Итак, мы можем просто кодировать:

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

Объяснение:

Нам не нужно передавать какой-либо параметр или проверять, существует ли папка, или даже передавать параметр mode, если это не требуется; по следующим причинам:

  • Команда создаст папку с разрешением 0755 (разрешение по умолчанию для папки общего хостинга) или 0777 по умолчанию для команды.
  • modeигнорируется на хостинге Windows с PHP .
  • У mkdirкоманды уже есть встроенная программа проверки, если папка существует; поэтому нам нужно проверять возврат только True | False; и это не ошибка, это только предупреждение, и предупреждение отключено на хост-серверах по умолчанию.
  • Что касается скорости, это быстрее, если предупреждение отключено.

Это просто еще один способ разобраться в вопросе и не требовать лучшего или наиболее оптимального решения.

Протестировано на PHP7, Производственный сервер, Linux



2

Мы всегда должны модульно кодировать наш код, и я написал ту же самую проверку ниже. Сначала мы проверяем каталог, если каталог отсутствует, мы создаем каталог.

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

1

Сначала нужно проверить, существует ли каталог file_exists('path_to_directory')

Затем используйте mkdir(path_to_directory)для создания каталога

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

Подробнее о mkdir () здесь

Полный код здесь:

$structure = './depth1/depth2/depth3/';
if (!file_exists($structure)) {
    mkdir($structure);
}

0

Ну вот.

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'));
    }
}

PHPStorm (с проверками PHP) дает именно это предложение ;-) Кстати. вы можете объединить внешнее if с внутренним: if (! is_dir (...) &&! mkdir (...) &&! is_dir (...)) ...
aProgger

-1

Принятый ответ работает, но это не правильное решение из-за разрешений. Разрешения 0777 позволяют каждому получить доступ / читать / писать каталог. Это не то, что мы хотим для загрузки каталога на веб-сервере. Вот правильное и полное предлагаемое решение.

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

0644 - это правильные разрешения для каталога загрузки, потому что мы обычно не хотим, чтобы загрузка на сервере выполнялась там.

true является третьим параметром для установки рекурсивного свойства в true или false. Это позволяет создавать вложенные каталоги, указанные в пути.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.