ฉันจะตรวจสอบว่ามีไดเรกทอรีอยู่ได้อย่างไร? “ is_dir”,“ file_exists” หรือทั้งสองอย่าง?


329

ฉันต้องการสร้างไดเรกทอรีถ้ามันไม่มีอยู่แล้ว

มีการใช้งานis_dirเพียงพอสำหรับวัตถุประสงค์ดังกล่าวหรือไม่

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

หรือฉันควรรวมis_dirกับfile_exists?

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

3
โอเปอเรเตอร์บูลีนหรือควรเป็นและและใน PHP มันถูกเขียนเป็น &&
Ivo Renkema

15
@IvoRenkema PHP ยังสนับสนุนor/ andนอกเหนือจาก/|| &&
Camilo Martin

1
ผู้ประกอบการ&&ไม่สนใจที่นี่เพราะหากไฟล์ไม่มีอยู่ ( !file_exists($dir) == true) ตรวจสอบว่าไม่ใช่ไดเรกทอรี และถ้าไฟล์ที่มีอยู่!is_dir($dir)จะไม่ได้รับการตรวจสอบเพราะ!file_exists($dir)จะกลับมาfalseและ&&ผู้ประกอบการเป็นลัดวงจร
Boolean_Type

4
ในมุมมองของฉันผู้ประกอบการควรจะเป็นหรือ
Mojtaba

ด้วย && สิ่งนี้ทำงานได้อย่างสมบูรณ์แบบสำหรับฉัน
FABBRj

คำตอบ:


220

ทั้งสองจะกลับมาจริงในระบบ Unix - ใน Unix ทุกอย่างเป็นไฟล์รวมถึงไดเรกทอรี แต่เพื่อทดสอบว่าใช้ชื่อนั้นหรือไม่คุณควรตรวจสอบทั้งคู่ อาจมีไฟล์ปกติที่ชื่อว่า 'foo' ซึ่งจะป้องกันไม่ให้คุณสร้างชื่อไดเรกทอรี 'foo'


37
อย่าลืมตรวจสอบว่า is_writable หรือไม่
Drewdin

10
@Drewdin คุณต้องการตรวจสอบผู้ปกครองis_writableหรือไม่
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
สิ่งที่เสียงก้องพูดนั้น…
kay - SE เป็นสิ่งชั่วร้าย

13
เมื่อพิจารณาจะใช้การป้อนข้อมูลโพสต์และใช้ตามที่เป็นอยู่บวกทำให้ 0777 dir ไม่ปลอดภัยเท่านี้เลย P
sEver

2
อย่างจริงจังยิ่งขึ้น $ dirname สามารถถูกทำให้สะอาดได้และการอนุญาตสามารถตั้งค่าเป็น 0755 เพิ่มไปยังคำสั่ง. htaccess บางรายการ มีคำแนะนำเพิ่มเติมเกี่ยวกับที่ 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
เมื่อคุณใช้mkdir- ทำไมคุณไม่ผ่าน '$ filename'?
Howdy_McGee

17

ฉันคิดว่า realpath () อาจเป็นวิธีที่ดีที่สุดในการตรวจสอบหากมีเส้นทางอยู่ http://www.php.net/realpath

นี่คือฟังก์ชั่นตัวอย่าง:

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

เวอร์ชั่นสั้นของฟังก์ชั่นเดียวกัน

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

ตัวอย่างผลลัพธ์

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

การใช้

<?php

$folder = '/foo/bar';

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

mkdir($folder);
// Continue do stuff

2
สำหรับทุกคนที่เจอสิ่งนี้ฉันเชื่อว่า realpath แคชโฟลเดอร์เมื่อมันทำงานดังนั้นถ้ามันทำงานครั้งเดียวแล้วโฟลเดอร์จะถูกลบออกหลังจากนั้นมันอาจไม่กลับเท็จถ้าทำงานอีกครั้ง
Jase

2
แต่ file_exists ก็เช่นกัน
Sebas

7

ตัวแปรที่สองในการโพสต์คำถามไม่เป็นไรเพราะถ้าคุณมีไฟล์ที่มีชื่อเดียวกันอยู่แล้ว แต่ไม่ใช่ไดเรกทอรี!file_exists($dir)จะส่งคืนfalseโฟลเดอร์จะไม่ถูกสร้างขึ้นดังนั้นข้อผิดพลาด"failed to open stream: No such file or directory"จะเกิดขึ้น ใน Windows มีความแตกต่างระหว่างประเภท 'ไฟล์' และ 'โฟลเดอร์' ดังนั้นจึงจำเป็นต้องใช้file_exists()และis_dir()ในเวลาเดียวกันเช่น:

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
คุณสามารถตรวจสอบเส้นทางแบบเต็มและหากไม่มีอยู่ให้สร้างด้วย mkdir ซ้ำ: if (! file_exists ($ filename2)) {mkdir ($ filename2, 0777, true); } นอกจากนี้คุณรหัสกำลังจะไม่สร้างเส้นทางแบบเต็มถ้า $ ชื่อไฟล์ไม่ได้อยู่ ...
นีลส์อาร์

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

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

3
การตั้งค่า chmod 777 ไม่ใช่ความคิดที่ดี 755 เพียงพอสำหรับโฟลเดอร์
Oldskool

2

เพิ่มจริงหลังจาก 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

if(stream_resolve_include_path($folder)!==false)ดีแทนการตรวจสอบทั้งสองที่คุณสามารถทำได้ มันช้ากว่าแต่ฆ่านกสองตัวในนัดเดียว

อีกตัวเลือกหนึ่งก็คือการไม่สนใจE_WARNING, ไม่โดยใช้@mkdir(...);(เพราะนั่นก็จะสละคำเตือนที่เป็นไปได้ทั้งหมดไม่เพียงไดเรกทอรีที่มีอยู่แล้วอย่างใดอย่างหนึ่ง) แต่โดยการลงทะเบียนจัดการข้อผิดพลาดที่เฉพาะเจาะจงก่อนที่จะทำมัน

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

ฉันมีข้อสงสัยเหมือนกัน แต่ดู PHP docu:

https://www.php.net/manual/en/function.file-exists.php

https://www.php.net/manual/en/function.is-dir.php

คุณจะเห็นว่า is-dir มีคุณสมบัติทั้งสองอย่าง

Return Values ​​is_dir ส่งคืน TRUE หากมีชื่อไฟล์อยู่และเป็นไดเรกทอรี FALSE เป็นอย่างอื่น


1

นี่เป็นคำถามเก่า แต่ยังคงเป็นหัวข้อเฉพาะ เพียงแค่ทดสอบด้วยis_dir()หรือfile_exists()ฟังก์ชั่นสำหรับการปรากฏตัวของ.หรือ..ไฟล์ในไดเรกทอรีภายใต้การทดสอบ แต่ละไดเรกทอรีจะต้องมีไฟล์เหล่านี้:

is_dir("path_to_directory/.");    

0

นี่คือวิธีที่ฉันทำ

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

เมื่อตอบคำถามเก่าคำตอบของคุณจะมีประโยชน์มากขึ้นสำหรับผู้ใช้ StackOverflow รายอื่นหากคุณรวมบริบทเพื่ออธิบายว่าคำตอบของคุณช่วยได้อย่างไรโดยเฉพาะอย่างยิ่งสำหรับคำถามที่มีคำตอบที่ยอมรับแล้ว ดู: ฉันจะเขียนคำตอบที่ดีได้อย่างไร
David Buck

0

วิธีตรวจสอบว่าพา ธ คือไดเร็กทอรีสามารถติดตามได้หรือไม่:

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

หมายเหตุ: มันจะส่งคืนค่าเท็จสำหรับพา ธ ที่ไม่มีอยู่ด้วย แต่จะทำงานได้อย่างสมบูรณ์แบบสำหรับ UNIX / Windows

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