web-dev-qa-db-fra.com

php glob - recherche dans un sous-dossier un sous-dossier

J'ai un serveur avec beaucoup de fichiers dans divers dossiers, sous-dossiers et sous-sous-dossiers. 

J'essaie de créer une page search.php qui serait utilisée pour rechercher un fichier spécifique sur l'ensemble du serveur. Si le fichier est trouvé, renvoyez le chemin de l'emplacement pour afficher un lien de téléchargement.

Voici ce que j'ai jusqu'à présent:

$root = $_SERVER['DOCUMENT_ROOT'];
$search = "test.Zip";
$found_files = glob("$root/*/test.Zip");
$downloadlink = str_replace("$root/", "", $found_files[0]);
if (!empty($downloadlink)) {
    echo "<a href=\"http://www.example.com/$downloadlink\">$search</a>";
} 

Le script fonctionne parfaitement si le fichier se trouve à la racine de mon nom de domaine ... Maintenant, j'essaie de trouver un moyen de le faire aussi pour analyser les sous-dossiers et les sous-sous-dossiers, mais je suis coincé ici.

26
Winston Smith

Il y a 2 façons.

Utilisez glob pour effectuer une recherche récursive:

<?php

// Does not support flag GLOB_BRACE
function rglob($pattern, $flags = 0) {
    $files = glob($pattern, $flags); 
    foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir) {
        $files = array_merge($files, rglob($dir.'/'.basename($pattern), $flags));
    }
    return $files;
}

?>

Utilisez RecursiveDirectoryIterator

<?php
function rsearch($folder, $pattern) {
    $dir = new RecursiveDirectoryIterator($folder);
    $ite = new RecursiveIteratorIterator($dir);
    $files = new RegexIterator($ite, $pattern, RegexIterator::GET_MATCH);
    $fileList = array();
    foreach($files as $file) {
        $fileList = array_merge($fileList, $file);
    }
    return $fileList;
}
?>

RecursiveDirectoryIterator est fourni avec PHP5 tandis que glob provient de PHP4. Les deux peuvent faire le travail, c'est à vous de décider.

51
Tony Chen

Ceci retourne le chemin complet du fichier

function rsearch($folder, $pattern) {
    $iti = new RecursiveDirectoryIterator($folder);
    foreach(new RecursiveIteratorIterator($iti) as $file){
         if(strpos($file , $pattern) !== false){
            return $file;
         }
    }
    return false;
}

appeler la fonction:

$filepath = rsearch('/home/directory/thisdir/', "/findthisfile.jpg");

Et cela revient comme:

/home/directory/thisdir/subdir/findthisfile.jpg

Vous pouvez améliorer cette fonction pour trouver plusieurs fichiers comme tous les fichiers jpeg:

function rsearch($folder, $pattern_array) {
    $return = array();
    $iti = new RecursiveDirectoryIterator($folder);
    foreach(new RecursiveIteratorIterator($iti) as $file){
        if (in_array(strtolower(array_pop(explode('.', $file))), $pattern_array)){
            $return[] = $file;
        }
    }
    return $return;
}

Cela peut appeler comme: 

$filepaths = rsearch('/home/directory/thisdir/', array('jpeg', 'jpg') );

Réf.: https://stackoverflow.com/a/1860417/219112

4
Sadee

Je souhaite proposer une autre solution simple pour les cas où vous pouvez prévoir une profondeur maximale. Vous pouvez utiliser un modèle avec des accolades répertoriant toutes les profondeurs possibles de sous-dossiers.

Cet exemple autorise 0-3 sous-dossiers arbitraires:

glob("$root/{,*/,*/*/,*/*/*/}test_*.Zip", GLOB_BRACE);

Bien entendu, le motif en forme de contreventement pourrait être généré de manière procédurale.

1
Quasimodo's clone

En tant que solution complète à votre problème (c'était aussi mon problème):

<?php
function rsearch($folder, $pattern) {
    $dir = new RecursiveDirectoryIterator($folder);
    $ite = new RecursiveIteratorIterator($dir);
    $files = new RegexIterator($ite, $pattern, RegexIterator::MATCH);
    $fileList = array();
    foreach($files as $file) {
         $fileList[] = $file->getPathName();
    }
    return $fileList;
}
?>

Vous obtiendrez le chemin complet des articles que vous souhaitez trouver.

0
metzelder