IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

EDI, CMS, Outils, Scripts et API PHP Discussion :

Trouver chaine dans nom fichier


Sujet :

EDI, CMS, Outils, Scripts et API PHP

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut Trouver chaine dans nom fichier
    Bonsoir à tous,

    Je galère depuis qq temps sur un pb probablement stupide pour certains caïds de PHP

    Dans un dossier je veux compter le nombre de fichier dont le nom comporte la chaîne "executive", mon code (qui ne fonctionne pas) est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $dossier = '../dossierPerso/dossierIndividuel/';
     
    if (is_dir($dossier)) {
        $nbre = 0;	// nbre total de fichiers dans dos
    	$nbre1 = 0;	// nbre de fichiers sélectionnés
    	if ($dh = opendir($dossier)) {
            while (($file = readdir($dh)) != false) {
    			 $nbre++;
    			 if(strrpos($file['filename'], "executive", 0) != false) $nbre1++;
    			 echo basename($file) ." ==> ".strrpos(basename($file), "executive", 0)." ==> ".$nbre."<br />";
            }
            closedir($dh);
        }
    }	/**/
    echo "<br />Nbre total de fichiers = ".$nbre."nbre filtés = ".$nbre1."<br />";
    J'ai essayer diverses chose, rien ne fonctionne.

    Si qqu'un peut m'aider d'avance merci

  2. #2
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Ne pourrais-tu pas utiliser la fonction glob de php ?

    Sinon il y a aussi la spl avec DirectoryIterator et FilesystemIterator sur lesquels tu pourrais appliquer RegexIterator ou FilterIterator

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $dossier = '../dossierPerso/dossierIndividuel/';
    $match = '#.*executive.*#';
     
    $files = new FilesystemIterator($dossier);
    $recherche = new RegexIterator ($files,$match);
     
    // nombre de fichiers comportant le masque $match
    echo iterator_count($recherche);
    echo '<br>';
     
    // liste les fichiers
    foreach ($recherche as $fichiers)
    echo $fichiers->getFilename().'<br>';

  3. #3
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Plus haut je t'ai donné un exemple de code avec RegexIterator (j'ai édité mon message) mais à partir de php 5.4 tu peux aussi utiliser "CallbackFilterIterator"

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $dossier = '../dossierPerso/dossierIndividuel/';
     
    $files = new FilesystemIterator($dossier);
     
    // Filtre les fichiers (doit être un fichier et inclure 'executive')
    $filtre = new CallbackFilterIterator($files, function ($current, $key, $iterator) {
        return $current->isFile() && strpos($current->getFilename(),'executive') !== false;
    });
     
    // nombre de fichiers filtrés
    echo iterator_count($filtre);
    echo '<br>';
     
    foreach ($filtre as $fichiers)
    echo $fichiers->getFilename().'<br>';

    Et avant php 5.4 on peut utiliser FilterIterator comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class filtre extends FilterIterator 
    {
    	private $userFilter;
     
    	function __construct($iterator , $filter)
    	{
    		parent::__construct($iterator);
                    $this->userFilter = $filter;
    	}
     
    	public function accept()
    	{
    		$current = parent::current();
    		return $current->isFile() && strpos($current->getFilename(),$this->userFilter) !== false;
    	}	
    }
     
    $dossier = '../dossierPerso/dossierIndividuel/';
    $strpos = 'executive';
     
    $fichiers = new FilesystemIterator($dossier);
    $tri = new filtre($fichiers,$strpos);
     
    echo iterator_count($tri);
    echo '<br>';
    foreach ($tri as $fichiers)
    echo $fichiers->getFilename().'<br>';
    Bon là j'ai affiné un peu pour pouvoir externaliser le critère de recherche mais on peut faire plus court.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Merci pour ta réponse,
    NI-CKELhttp://www.developpez.net/forums/images/smilies/ccool.gif je pense rarement à utiliser ces fonctions iterator.

    Interrogation de ma part , ton masque $match = '#.*executive.*#'; ne serai pas plutôt $match = '#.*executive*.#'; ou je n'ai rien compris http://www.developpez.net/forums/ima...s/icon_sad.gif

    Dernier petit conseil, comment ferai-tu le masque pour récupérer ce qui est un decimal et se trouve entre une consonne et une parenthèse (.

    J'ai un autre groupe de fichier dans ce dossier qui répertoriés :
    modeleBP1(date...).xls
    modeleBP2(date...).xls
    modeleBP3(date...).xls
    modeleBP4(date...).xls
    modeleBP5(date...).xls

    Je souhaite connaître l'indice le plus grand lors d'une création de fichier et pouvoir incrémenter ce nouveau fichier?

    D'avance merci

  5. #5
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Tu mets des caractères spéciaux (des parenthèses) dans le nom de tes fichiers ? Cela pose souvent des problèmes... à éviter. Faudrait voir à changer cela. Le plus simple serait d'avoir des fichiers du genre "modeleBP1.xls" (sans la date) et dans ce cas ce serait assez facile à incrémenter. Par exemple cette fonction qui est une option de cette classe d'upload :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    // Fonction de renommage : si fichier.ext existe, renomme en fichier1.ext ;  si fichier1.ext existe, renomme en fichier2.ext etc..
    function Rename_fich($adresse_fichier)
    {      
             // si le nom du fichier existe déjà
            if (is_file($adresse_fichier))
                    {
                            $info = pathinfo($adresse_fichier);
                            $extension = isset($info['extension'])? '.'.$info['extension'] : null;
                            $dossier = $info['dirname'];
                            $basename = $info['basename'];
     
                             // fichier sans extension
                            // pour compatibilité php 5.1, sinon avec php 5.2 on pourrait récupérer $info['filename']
                            $filename = isset($extension) && strrpos($basename,$extension) !== false ? substr($basename,0,strrpos($basename,$extension)) : $basename;
     
                            //addcslashes pour protéger les points dans les regex (et qu'ils ne soient pas pris pour un caractère spécial réservé)
                            $file = addcslashes($filename,'.');
     
                            // idem sur l'extension        
                            $ext = isset($extension) ? addcslashes($extension,'.') : null;
     
                            //expression régulière, cherche les 'nb' (nb = nombre)  à la fin du nom d'un fichier                                                       
                            $match = isset($extension)? '#^'.$file.'[0-9]+'.$ext.'$#' : '#^'.$file.'[0-9]+$#';
     
                            $tab_identique = array();
     
                            // tableau des fichiers correspondants à la recherche  en utilisant $match    
                            if(class_exists('RegexIterator')) // test car n'existe qu'à partir de php 5.2
                                    {
                                            $files = new RegexIterator(new DirectoryIterator($dossier),$match);
                                            foreach ($files as $fileinfo) $tab_identique[] = $fileinfo->getFilename();
                                    }      
                                    else // pour compatibilité php 5.1
                                    {      
                                            $files = new DirectoryIterator($dossier);                      
                                            foreach ($files as $fileinfo) if (preg_match($match,$fileinfo->getFilename())) $tab_identique[] = $fileinfo->getFilename();    
                                    }
                            // Tri du tableau des résultats par ordre alphabétique               
                            natsort($tab_identique);
     
                            // Prend le dernier élément du tableau (qui après tri est celui avec la plus grande incrémentation)        
                            $dernier = array_pop($tab_identique);
     
                            // efface le tableau devenu inutile            
                            unset($tab_identique);
     
                          // vérifie que dernier élément existe et si oui enlève l'extension
                          $dernier = isset($dernier) ? basename($dernier,$extension) : "";
     
                         // Incrémente le nom du dernier fichier (avec return $matches[1]+1)
                         $file = preg_replace_callback('#([0-9]+$)#', create_function('$matches','return $matches[1]+1;'), $dernier, '1', $count);
     
                        // Si l'incrémentation est réussie (et donc qu'il existait préalablement un fichier incrémenté) on garde le résultat sinon on initialise une incrémentation avec 1                                                   
                        $filename = !empty($count)? $file : $filename.'1';
     
                        // On réintègre l'extension si elle existe                         
                        $filename = !empty($extension) ? $filename.$extension : $filename;
     
                            // on réintègre le dossier pour avoir une adresse complète                                                                                                                                    
                            $adresse = $dossier.'/'.$filename;
     
                            // On refait un test pour voir si ce nom de fichier existe; si non on retourne l'adresse
                            if (!is_file($adresse)) return $adresse; 
                 else                                                                                                                         //si oui on repasse par la fonction
                            return Rename_fich($adresse_fichier);                        
            }
     
            else
            {
                    return $adresse_fichier;
            }
    }
    Remarque que si c'est pour faire un upload tu pourrais te servir de la classe d'upload qui intègre cette fonctionnalité en option.

    Sinon et si tu ne peux pas changer le nom de tes fichiers (il est cependant très recommandé d'éviter les caractères spéciaux dans les noms de fichiers), tu peux essayer de t'inspirer de cette fonction.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Merci pour tes remarques,

    Effectivement ces fichiers viennent d'un autre script qui génère le nom avec la date entre parenthèses, n'ayant jamais rencontrer de pb avec ceci je n'avais guère prêter attention à ce pb.

    Je vais remédier à ceci et vais essayer de faire un masque de regex pour récupérer la partie décimal du filename.
    J'imagine que qq chose du genre "[\d+]" comme en JS doit fonctionner.

    Dernier point comment extraire la date de modif du dossier avec «FilesystemIterator», j viens de rapidement regarder sans trouver de soluce.

    Encore merci

  7. #7
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Si tu veux un code générique c'est plus pratique de mettre l'incrémentation toujours en fin de fichier juste avant l'extension comme "modeleBP1.xls", "modeleBP2.xls" ou "modeleBP_1.xls", "modeleBP_2.xls", ou modeleBP_v1.xls, modeleBP_v2.xls etc.
    Sinon il est impossible de créer un masque pour l'ensemble des fichiers et il faudrait réécrire ton masque pour chaque fichier. Car pour peu qu'un nom de fichier possède un chiffre qui ne corresponde pas à une incrémentation, comment vas-tu le reconnaître si tes fichiers n'ont pas une structure commune pour l'incrémentation ?


    Pour avoir la date de dernière modification c'est la méthode "getCTime()" qui retourne un timestamp donc pour avoir une date au format français on pourrait faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo $fichiers->getFilename().' '.date("d/m/Y H:i",$fichiers->getCTime()).'<br>';

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Encore mille mercis,

    Pour la date de modif jai essayé d'utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    filemtime($fichiers->getFilename())
    Qui ne fonctionne pas.

    Ton script fonctionne lui pafaitement.

    Concernant l'incrémentation j'ai écrit ce script qui me va bien

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    preg_match("/[0-9]{1,2}/", $fichiers->getFilename(), $matches); // Qui récupère la première occurrence numérique (les noms de fichiers ont tous la même structure hkhkhkhkj12khkhkjhkj.docx)
    array_push($stack, $matches[0]);
    arsort($stack);   //   tri inverse du tableau;
    print_r($stack);
    $max = $stack[0];  //  base de l'incrémantation
    echo "max : ".$max;

  9. #9
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    C'est pas un peu risqué de limiter le nombre à deux chiffres ?

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Oui effectivement mais dans le cas d'espèce cela suffit amplement.

    Bonne soirée
    Cdlt

  11. #11
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Oui c'est possible mais en général on fait des restrictions si besoin surtout pour contrôle. Par contre quand il ne s'agit pas de sécurité, ni de valider l'application on a plutôt tendance à être large pour ne pas avoir à corriger par la suite en cas d'évolution ou tout simplement pour faire du code plus facilement réutilisable. Avec un [0-9]{1,} ou [0-9]+ tu obtiens le même résultat sans restrictions. Enfin bon c'était juste pour parler...

    Autre remarque, ta manière de faire est correcte uniquement si les fichiers de ton répertoire ont tous la même extension. Sinon l'incrémentation d'un fichier ".xls" pourrait être incrémenté à cause d'un ".docx" déjà existant par exemple. Même remarque si les noms des fichiers ont des préfixes différents. C'est bien pour cette raison que dans la fonction que j'ai donné en exemple plus haut, j'intègre le nom du fichier et son extension dans le regex pour faire la recherche.

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Ah oui je n'avais pas pensé à ce pb.

    Je regarde ceci dans la journée.

    Encore merci pour tes conseils.

    Cdlt

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Bonjour, je reviens vers vous j'utilise avec succès la soluce « FilesystemIterator » donnée par ABCIWEB mais maintenant je voudrais inclure les fichiers de subdir et là je pédale fort ?
    Si qqu'un peut m'aider d'avance merci

  14. #14
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Citation Envoyé par bronon Voir le message
    Bonjour, je reviens vers vous j'utilise avec succès la soluce « FilesystemIterator » donnée par ABCIWEB mais maintenant je voudrais inclure les fichiers de subdir et là je pédale fort ?
    Qu'entends-tu par "subdir" ? Si tu veux travailler sur tous les fichiers, répertoires et sous répertoires d'un dossier, tu peux utiliser la classe recursivedirectoryiterator et pour filtrer avec un regex, utiliser la classe recursiveregexiterator

  15. #15
    Membre habitué
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    414
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 414
    Points : 187
    Points
    187
    Par défaut
    Merci pour ta réponse,
    J'avais essayé cette recursiveregexiterator mais je ne m'en suis pas sorti d'ou mon appel au secours.
    Si tu peux me guider ça serait sympa !
    Cdlt
    [MàJ]
    Ce matin j'ai mis en place le le script suivant qui fonctionne bien pour les sub directory mais refuse d'afficher les fichiers du 1er niveau, pourquoi ?
    Mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    $rArrayIterator = new RecursiveArrayIterator(array('test1', array('tet3', 'test4', 'test5')));
    $dir = realpath('../../JS/');
    $rDirectory = new RecursiveDirectoryIterator($dir);
     
    $rRegexIterator = new RecursiveRegexIterator($rDirectory, '/\.js$/',
        RecursiveRegexIterator::ALL_MATCHES);
     
    foreach ($rRegexIterator as $key1 => $value1) {
     
        if ($rRegexIterator->hasChildren()) {
     
            // Affiche tous les enfants
            echo "<br />Children : <br />";
            foreach ($rRegexIterator->getChildren() as $key => $value) {
                echo $value ."<br />";
            }
            echo "<br />";
        } else {
            echo "1er niveau : <br />";
            foreach ($rRegexIterator as $key => $value) {
                echo $value. "<br />";
            }	
        }
     
    }
    Encore merci pour ton aide

  16. #16
    Expert éminent sénior

    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2010
    Messages
    5 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2010
    Messages : 5 380
    Points : 10 410
    Points
    10 410
    Par défaut
    Oui elle est pas très sexy la SPL. Essaies comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $dossier = 'dossier-cible';
    $match = '#.*executive.*#';
     
    $files = new RecursiveDirectoryIterator($dossier,FilesystemIterator::SKIP_DOTS|FilesystemIterator::CURRENT_AS_SELF);
     
    $total_sub = new RecursiveIteratorIterator($files);
     
    $recherche = new RegexIterator($total_sub,$match);
     
    foreach ($recherche as $fichiers) echo $fichiers->getFilename().'<br>';

Discussions similaires

  1. rechercher n'importe quelle chaine dans nom de fichier
    Par mr.choum dans le forum VBScript
    Réponses: 6
    Dernier message: 18/07/2012, 13h21
  2. Rechercher sous-chaine dans nom fichier
    Par leuke dans le forum Scripts/Batch
    Réponses: 8
    Dernier message: 17/06/2009, 18h11
  3. enregistrer une liste chainée dans un fichier?
    Par ALF-Teams dans le forum C
    Réponses: 7
    Dernier message: 08/03/2006, 19h42
  4. Réponses: 21
    Dernier message: 29/09/2005, 20h33
  5. [Stratégie]Sauvegarde d'une liste chainée dans un fichier
    Par BernardT dans le forum Général Java
    Réponses: 17
    Dernier message: 25/07/2005, 18h04

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo