PHP Obtener todos los subdirectorios de un directorio dado

139

¿Cómo puedo obtener todos los subdirectorios de un directorio dado sin archivos, .(directorio actual) o ..(directorio principal) y luego usar cada directorio en una función?

Adrian M.
fuente

Respuestas:

210

puedes usar glob () con la GLOB_ONLYDIRopción

o

$dirs = array_filter(glob('*'), 'is_dir');
print_r( $dirs);
ghostdog74
fuente
que da subdirectorios también?
Gordon
2
Tienes que resurgir aquí
Josef Sábl
Lo sentimos, ¿dónde está la opción GLOB_ONLYDIR aquí?
developerbmw
55
@developerbmw Tenga en cuenta la palabra o . Presenta dos métodos diferentes para alcanzar la meta.
Ken Wayne VanderLinde
77
Si bien es un enfoque simple y agradable, la respuesta aceptada no responde a la pregunta: obtener subdirectorios del directorio principal (también conocido como hermanos del directorio de trabajo actual). Para hacerlo, necesitaría cambiar el directorio de trabajo al directorio principal.
ryanm
156

Así es como puede recuperar solo directorios con GLOB:

$directories = glob($somePath . '/*' , GLOB_ONLYDIR);
Coreus
fuente
2
Esto también incluye el directorio principal.
user4951
3
Esto no incluye el directorio principal en mi caso (Windows)
marcovtwout
1
Esto tampoco incluye el directorio principal para mí en Mac Linux. Tal vez tiene que ver con el camino utilizado?
Jake
1
Esto incluye también el camino $somePathen la salida
The Godfather
47

La clase Spl DirectoryIterator proporciona una interfaz simple para ver el contenido de los directorios del sistema de archivos.

$dir = new DirectoryIterator($path);
foreach ($dir as $fileinfo) {
    if ($fileinfo->isDir() && !$fileinfo->isDot()) {
        echo $fileinfo->getFilename().'<br>';
    }
}
stloc
fuente
27

Casi lo mismo que en su pregunta anterior :

$iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($yourStartingPath), 
            RecursiveIteratorIterator::SELF_FIRST);

foreach($iterator as $file) {
    if($file->isDir()) {
        echo strtoupper($file->getRealpath()), PHP_EOL;
    }
}

Reemplace strtouppercon su función deseada.

Gordon
fuente
1
¡genial gracias! Una pregunta más: ¿cómo puedo separar solo el nombre del subdirectorio de la ruta completa?
Adrian M.
@Adrian Por favor, eche un vistazo a la documentación API que le di en su otra pregunta. getFilename()solo devolverá el nombre del directorio.
Gordon
1
Para deshacerme de los puntos, tuve que agregar RecursiveDirectoryIterator::SKIP_DOTScomo segundo argumento al RecursiveDirectoryIteratorconstructor.
colan
5

Prueba este código:

<?php
$path = '/var/www/html/project/somefolder';

$dirs = array();

// directory handle
$dir = dir($path);

while (false !== ($entry = $dir->read())) {
    if ($entry != '.' && $entry != '..') {
       if (is_dir($path . '/' .$entry)) {
            $dirs[] = $entry; 
       }
    }
}

echo "<pre>"; print_r($dirs); exit;
keyur0517
fuente
4

En matriz:

function expandDirectoriesMatrix($base_dir, $level = 0) {
    $directories = array();
    foreach(scandir($base_dir) as $file) {
        if($file == '.' || $file == '..') continue;
        $dir = $base_dir.DIRECTORY_SEPARATOR.$file;
        if(is_dir($dir)) {
            $directories[]= array(
                    'level' => $level
                    'name' => $file,
                    'path' => $dir,
                    'children' => expandDirectoriesMatrix($dir, $level +1)
            );
        }
    }
    return $directories;
}

//acceso:

$dir = '/var/www/';
$directories = expandDirectoriesMatrix($dir);

echo $directories[0]['level']                // 0
echo $directories[0]['name']                 // pathA
echo $directories[0]['path']                 // /var/www/pathA
echo $directories[0]['children'][0]['name']  // subPathA1
echo $directories[0]['children'][0]['level'] // 1
echo $directories[0]['children'][1]['name']  // subPathA2
echo $directories[0]['children'][1]['level'] // 1

Ejemplo para mostrar todo:

function showDirectories($list, $parent = array())
{
    foreach ($list as $directory){
        $parent_name = count($parent) ? " parent: ({$parent['name']}" : '';
        $prefix = str_repeat('-', $directory['level']);
        echo "$prefix {$directory['name']} $parent_name <br/>";  // <-----------
        if(count($directory['children'])){
            // list the children directories
            showDirectories($directory['children'], $directory);
        }
    }
}

showDirectories($directories);

// pathA
// - subPathA1 (parent: pathA)
// -- subsubPathA11 (parent: subPathA1)
// - subPathA2 
// pathB
// pathC
Ricardo Canelas
fuente
2
<?php
    /*this will do what you asked for, it only returns the subdirectory names in a given
      path, and you can make hyperlinks and use them:
    */

    $yourStartingPath = "photos\\";
    $iterator = new RecursiveIteratorIterator( 
        new RecursiveDirectoryIterator($yourStartingPath),  
        RecursiveIteratorIterator::SELF_FIRST);

    foreach($iterator as $file) { 
        if($file->isDir()) { 
            $path = strtoupper($file->getRealpath()) ; 
            $path2 = PHP_EOL;
            $path3 = $path.$path2;

            $result = end(explode('/', $path3)); 

            echo "<br />". basename($result );
        } 
    } 

    /* best regards,
        Sanaan Barzinji
        Erbil
    */
?>
Sanaan Barzinji
fuente
2

Puedes probar esta función (se requiere PHP 7)

function getDirectories(string $path) : array
{
    $directories = [];
    $items = scandir($path);
    foreach ($items as $item) {
        if($item == '..' || $item == '.')
            continue;
        if(is_dir($path.'/'.$item))
            $directories[] = $item;
    }
    return $directories;
}
Jan-Fokke
fuente
1

Forma apropiada

/**
 * Get all of the directories within a given directory.
 *
 * @param  string  $directory
 * @return array
 */
function directories($directory)
{
    $glob = glob($directory . '/*');

    if($glob === false)
    {
        return array();
    }

    return array_filter($glob, function($dir) {
        return is_dir($dir);
    });
}

Inspirado por Laravel

Macbric
fuente
1
Esto parece excesivo cuando hay una bandera GLOB_ONLYDIR, ver php.net/manual/en/function.glob.php
Robert Pounder
0

Este es el código único:

 $sub_directories = array_map('basename', glob($directory_path . '/*', GLOB_ONLYDIR));
Sultán
fuente
0

Directorios de lista no recursiva solamente

La única pregunta que hizo directamente esto se ha cerrado erróneamente, así que tengo que ponerla aquí.

También le da la capacidad de filtrar directorios.

/**
 * Copyright © 2020 Theodore R. Smith <https://www.phpexperts.pro/>
 * License: MIT
 *
 * @see https://stackoverflow.com/a/61168906/430062
 *
 * @param string $path
 * @param bool   $recursive Default: false
 * @param array  $filtered  Default: [., ..]
 * @return array
 */
function getDirs($path, $recursive = false, array $filtered = [])
{
    if (!is_dir($path)) {
        throw new RuntimeException("$path does not exist.");
    }

    $filtered += ['.', '..'];

    $dirs = [];
    $d = dir($path);
    while (($entry = $d->read()) !== false) {
        if (is_dir("$path/$entry") && !in_array($entry, $filtered)) {
            $dirs[] = $entry;

            if ($recursive) {
                $newDirs = getDirs("$path/$entry");
                foreach ($newDirs as $newDir) {
                    $dirs[] = "$entry/$newDir";
                }
            }
        }
    }

    return $dirs;
}
Theodore R. Smith
fuente
-1

Encuentra todos los archivos PHP de forma recursiva. La lógica debe ser lo suficientemente simple como para modificarla y pretende ser rápida (er) evitando llamadas a funciones.

function get_all_php_files($directory) {
    $directory_stack = array($directory);
    $ignored_filename = array(
        '.git' => true,
        '.svn' => true,
        '.hg' => true,
        'index.php' => true,
    );
    $file_list = array();
    while ($directory_stack) {
        $current_directory = array_shift($directory_stack);
        $files = scandir($current_directory);
        foreach ($files as $filename) {
            //  Skip all files/directories with:
            //      - A starting '.'
            //      - A starting '_'
            //      - Ignore 'index.php' files
            $pathname = $current_directory . DIRECTORY_SEPARATOR . $filename;
            if (isset($filename[0]) && (
                $filename[0] === '.' ||
                $filename[0] === '_' ||
                isset($ignored_filename[$filename])
            )) 
            {
                continue;
            }
            else if (is_dir($pathname) === TRUE) {
                $directory_stack[] = $pathname;
            } else if (pathinfo($pathname, PATHINFO_EXTENSION) === 'php') {
                $file_list[] = $pathname;
            }
        }
    }
    return $file_list;
}
SilbinaryWolf
fuente
La pregunta no pedía una lista de archivos, ni ninguna recursividad. Solo una lista de directorios en un directorio dado.
miken32
Estoy bien enterado. En ese momento, creo que esta fue la respuesta principal en Google o similar, así que agregué mi solución para aquellos que buscan una implementación recursiva que no arruine la pila. No veo ningún daño en proporcionar algo que pueda reducirse para resolver el problema original.
SilbinaryWolf
-1

Si está buscando un directorio recursivo con soluciones de listado. Use el siguiente código, espero que le ayude.

<?php
/**
 * Function for recursive directory file list search as an array.
 *
 * @param mixed $dir Main Directory Path.
 *
 * @return array
 */
function listFolderFiles($dir)
{
    $fileInfo     = scandir($dir);
    $allFileLists = [];

    foreach ($fileInfo as $folder) {
        if ($folder !== '.' && $folder !== '..') {
            if (is_dir($dir . DIRECTORY_SEPARATOR . $folder) === true) {
                $allFileLists[$folder . '/'] = listFolderFiles($dir . DIRECTORY_SEPARATOR . $folder);
            } else {
                $allFileLists[$folder] = $folder;
            }
        }
    }

    return $allFileLists;
}//end listFolderFiles()


$dir = listFolderFiles('your searching directory path ex:-F:\xampp\htdocs\abc');
echo '<pre>';
print_r($dir);
echo '</pre>'

?>
Faisal
fuente
-1

La siguiente función recursiva devuelve una matriz con la lista completa de subdirectorios

function getSubDirectories($dir)
{
    $subDir = array();
    $directories = array_filter(glob($dir), 'is_dir');
    $subDir = array_merge($subDir, $directories);
    foreach ($directories as $directory) $subDir = array_merge($subDir, getSubDirectories($directory.'/*'));
    return $subDir;
}

Fuente: https://www.lucidar.me/en/web-dev/how-to-get-subdirectories-in-php/

Fifi
fuente
La pregunta no pedía recursividad. Solo una lista de directorios en un directorio dado, que se les proporcionó en 2010.
miken32
-2

Encuentra todos los archivos y carpetas en un directorio específico.

function scanDirAndSubdir($dir, &$fullDir = array()){
    $currentDir = scandir($dir);

    foreach ($currentDir as $key => $val) {
        $realpath = realpath($dir . DIRECTORY_SEPARATOR . $val);
        if (!is_dir($realpath) && $filename != "." && $filename != "..") {
            scanDirAndSubdir($realpath, $fullDir);
            $fullDir[] = $realpath;
        }
    }

    return $fullDir;
}

var_dump(scanDirAndSubdir('C:/web2.0/'));

Muestra:

array (size=4)
  0 => string 'C:/web2.0/config/' (length=17)
  1 => string 'C:/web2.0/js/' (length=13)
  2 => string 'C:/web2.0/mydir/' (length=16)
  3 => string 'C:/web2.0/myfile/' (length=17)
A-312
fuente
Esta no es una respuesta completa, ya que no se puede ejecutar.
miken32
@ miken32 Es una respuesta completa, vuelva a intentarlo
A-312