สร้างโฟลเดอร์หากยังไม่มีอยู่


642

ฉันใช้งานบางกรณีด้วย WordPress ติดตั้งกับBluehostที่ฉันพบข้อผิดพลาดกับชุดรูปแบบ WordPress ของฉันเพราะโฟลเดอร์การอัปโหลดwp-content/uploadsไม่มีอยู่

เห็นได้ชัดว่าโปรแกรมติดตั้ง WordPress ของ Bluehost cPanelไม่ได้สร้างโฟลเดอร์นี้แม้ว่าHostGatorจะทำเช่นนั้น

ดังนั้นฉันต้องเพิ่มรหัสในธีมของฉันที่ตรวจสอบโฟลเดอร์และสร้างเป็นอย่างอื่น


7
if (!file_exists('path/to/directory')) { mkdir('path/to/directory', 0777, true); }
ฉันเป็นคนที่โง่ที่สุด

คำตอบ:


1227

ลองนี้โดยใช้mkdir :

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

โปรดทราบว่า0777เป็นโหมดเริ่มต้นสำหรับไดเรกทอรีอยู่แล้วและอาจยังสามารถแก้ไขได้โดย umask ปัจจุบัน


11
คุณพลาดสถานะ 'ซ้ำ' - ดูคำตอบของ Satish
Francois Bourgeois

118
is_dir () เร็วขึ้นเล็กน้อยกว่า file_exists ()
pliashkou

43
@YuryPliashkou ใช่แล้ว แต่มันไม่ได้ผลถ้ามีไฟล์ชื่อนั้นอยู่แล้ว
Gumbo

4
คำถามที่นี่: ดังนั้นหากมีไฟล์ชื่อ 'ไดเรกทอรี' ในเส้นทาง / ถึง, is_dir จะกลับจริง แต่ file_exists จะกลับเท็จ?
Igor L.

8
file_exists- ตรวจสอบว่ามีไฟล์หรือไดเรกทอรีอยู่หรือไม่ is_file- บอกว่าชื่อไฟล์เป็นไฟล์ปกติหรือไม่ is_dir- บอกว่าชื่อไฟล์เป็นไดเรกทอรีหรือไม่
TarranJones

137

นี่คือชิ้นส่วนที่ขาดหายไป คุณต้องผ่านการตั้งค่าสถานะ 'ซ้ำ' เป็นอาร์กิวเมนต์ที่สาม (บูลีนจริง) ในการโทรmkdirดังนี้:

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

8
ธง 'วนซ้ำ' เป็นอาร์กิวเมนต์บูลีนที่ 3true
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);
Battousai

ขอบคุณ @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ตรวจสอบที่เหมาะสมupvote ของฉันเป็นของคุณ :) คะแนนโบนัสสำหรับการตรวจสอบว่าไดเรกทอรีหลักis_writable()สำหรับฟังก์ชั่นผู้ช่วย watertight
Pekka

การใช้ @ เพื่อระงับข้อผิดพลาดคือประสิทธิภาพการทำงาน ดีกว่าที่จะตรวจสอบว่ามันไม่มีอยู่จริงแล้วเช่น Gumbo
Simon

1
โดยไม่คำนึงถึงการปราบปรามข้อผิดพลาดฉันมักจะ -1 สำหรับตัวอย่างแรก ที่สองดีกว่ามากว่าอันแรกนั้นไม่มีจุดหมาย
Justin Johnson

นี่เป็นเรื่องยากที่จะอ่านโค้ดเพียงเพื่อวางไว้บน 1 บรรทัด คำตอบที่ยอมรับนั้นชัดเจนกว่ามาก
MikeKulls

27

วิธีสร้างโฟลเดอร์ได้เร็วขึ้น:

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

นี้จะให้ข้อผิดพลาดหากมีไฟล์ชื่อ 'ไดเรกทอรี' ที่เส้นทางนั้น
Guney Ozsan


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
มันจะดีกว่าที่จะจัดการกับข้อผิดพลาดกว่าการปราบปรามพวกเขา หากสิ่งนี้ล้มเหลวคุณจะไม่มีทางรู้ว่าทำไมจากสิ่งนี้และจะต้องทำการวิจัย
Tim Ogilvy

ในสภาพแวดล้อมที่พร้อมกันสูง / แบบหลายเธรดขอแนะนำให้ระงับข้อผิดพลาด สภาวะการแย่งชิงอาจเกิดขึ้นที่สองหรือมากกว่ากระทู้จะประเมิน is_dir () เป็นเท็จและจะพยายามสร้างไดเรกทอรี เธรดแรกจะสามารถสร้างได้โดยไม่มีปัญหาใด ๆ แต่เธรดอื่นจะไม่สามารถทำได้เนื่องจากมีไดเรกทอรีอยู่แล้ว เพื่อหลีกเลี่ยงการหายไปของการสร้างไดเรกทอรีที่ล้มเหลวจริง ๆ คุณควรตรวจสอบการมีอยู่ของไดเรกทอรีหลังจากการเรียกไปที่ @mkdir () อีกครั้ง
tobain


2

เพื่อสร้างโฟลเดอร์หากยังไม่มีอยู่

พิจารณาสภาพแวดล้อมของคำถาม

  • WordPress
  • เว็บโฮสติ้งเซิร์ฟเวอร์
  • สมมติว่า Linux ไม่ใช่ Windows ที่ใช้งาน PHP

และข้อความจาก: http://php.net/manual/en/function.mkdir.php

บูล mkdir (สตริง $ pathname [, int $ mode = 0777 [, บูล $ recursive = FALSE [, ทรัพยากร $ บริบท]]])

คู่มือบอกว่าพารามิเตอร์ที่จำเป็นเท่านั้นคือ$pathname!

ดังนั้นเราสามารถโค้ด:

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

คำอธิบาย:

เราไม่จำเป็นต้องผ่านพารามิเตอร์ใด ๆ หรือตรวจสอบว่ามีโฟลเดอร์อยู่หรือแม้กระทั่งผ่านพารามิเตอร์โหมดเว้นแต่จำเป็น ด้วยเหตุผลดังต่อไปนี้:

  • คำสั่งจะสร้างโฟลเดอร์ที่มีสิทธิ์ 0755 (สิทธิ์เริ่มต้นของโฟลเดอร์โฮสติ้งที่แชร์) หรือ 0777 เป็นค่าเริ่มต้นของคำสั่ง
  • modeจะถูกละเว้นบนWindows Hosting ใช้ 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) ให้คำแนะนำนี้อย่างแน่นอน ;-) btw คุณสามารถรวมด้านนอกถ้าเข้าไปด้านใน: 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 เป็นพารามิเตอร์ที่สามสำหรับการตั้งค่าคุณสมบัติแบบเรียกซ้ำเป็นจริงหรือเท็จ อนุญาตให้สร้างไดเร็กทอรีที่ซ้อนกันที่ระบุในชื่อพา ธ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.