none
Chercher une chaîne dans des fichiers RRS feed

  • Question

  • Bonjour tout le monde,

    Pour chercher une chaîne de caractères dans les fichiers d'un répertoire et ses sous-répertoires, voici ce que j'utilise

    # FindString.ps1
    $r = $args[0];  # chaîne recherchée
    $f = $args[1];  # chemin
    $c = "";
    $c = Get-Content $args[1] -ea SilentlyContinue;
    if($c -match $r)
    {
       "========$f====================="
       $c -match $r;
       "==============================="
    }
    else
    {
      $f = $f;
    }
    #GetString.ps1
    $r = $args[0];  # chaîne recherchée
    Write-Host -f yellow -b magenta "$r                           "
    if($args[1] -ne "*")
    {
        $t = $args[1];   # masque des fichiers à analyser
        "Filtre sur $t";
    }
    $f = $args[2]; # chemin du répertoire
    gci $f -Include $t -recurse | foreach{$_.Length; D:\Scripts\FindString $r $_.FullName}

    Ça marche, mais par moments c'est horriblement long.

    Ça dépend des fichiers analysés, peut-être même des répertoires, mais je n'ai pas situé sur quel critère. Apparemment, la taille n'a pas grand-chose à y voir. Ça va assez vite de parcourir un projet MVC, en revanche si il y a Angular dedans il faut compter quelques minutes.

    Quelqu'un aurait-il des idées pour optimiser ça ?


    • Modifié Gloops lundi 4 mars 2019 09:47
    lundi 4 mars 2019 09:42

Réponses

  • Si je restreins la cible à un type de fichiers, il peut y avoir des grosses bêtes à côté (style dll ou exe) ça ne ralentira pas le traitement, pas vrai ?

    ouvrir un fichier inutile est toujours une perte de temps pour des fichiers comme les exe,
    surtout on est sur de ne pas y trouver ce qu'on recherche
    et encore plus si les fichiers sont volumineux

    Si je veux modifier le traitement en finesse ça risque de m'obliger à faire une couche de plus, en ne profitant pas du caractère récursif de l'instruction gci, pas vrai ?

    non tu rajouter des filtres mais tu garde le recursif. ex :  Get-ChildItem $f -Filter "*.txt" -recurse
    ou Get-ChildItem $f  -recurse | where {$_.Extension -eq ".txt"}
    ou Get-ChildItem $f  -recurse | where {$_.Extension -ne ".exe"}

    voici un exemple de traitement avec StreamReader qui est instruction la plus rapide pour la lecture de fichier :

    # FindString.ps1
    $r = $args[0]  # chaîne recherchée
    $f = $args[1]  # chemin
    $c = ""
    $hfichier = [System.IO.File]::Open($f,"Open","Read","ReadWrite")
    $stream = new-object System.IO.StreamReader($hfichier)
    $ligne = $stream.ReadLine()
    while ($ligne -ne $null) {
        if ($ligne -match $r) {
            "========$f====================="
            $ligne
            "==============================="
            }
        else {
            $f = $f
            }
        $ligne = $stream.ReadLine()
        }
    $stream.Close()


    • Modifié 6ratgus mardi 5 mars 2019 08:46
    • Marqué comme réponse Gloops mardi 5 mars 2019 09:50
    mardi 5 mars 2019 08:43

Toutes les réponses

  • salut 

    fait un test en changent que cette ligne :

    $c = Get-Content $args[1] -ea SilentlyContinue;
    

    en

    $c = Get-Content $args[1] -raw -ea SilentlyContinue;
    

    tu devrais gagner en vitesse

    sinon il y a d'autre solution mais elle sont plus adapter a des gros fichiers 

    lundi 4 mars 2019 14:07
  • OK merci, dans le principe ça devrait bien aider.

    J'ai quand même l'impression qu'il faudrait que je chronomètre pour me rendre compte si vraiment ça va plus vite.

    Ah, mais il y a une contre-partie : sans raw, quand il a trouvé l'argument de recherche ça m'affiche la ligne où il se trouve. Avec, ça m'affiche juste "True". Or, le but est quand même d'avoir une idée du contexte.

    Si je restreins la cible à un type de fichiers, il peut y avoir des grosses bêtes à côté (style dll ou exe) ça ne ralentira pas le traitement, pas vrai ?

    Si je veux modifier le traitement en finesse ça risque de m'obliger à faire une couche de plus, en ne profitant pas du caractère récursif de l'instruction gci, pas vrai ?

    lundi 4 mars 2019 14:38
  • Si je restreins la cible à un type de fichiers, il peut y avoir des grosses bêtes à côté (style dll ou exe) ça ne ralentira pas le traitement, pas vrai ?

    ouvrir un fichier inutile est toujours une perte de temps pour des fichiers comme les exe,
    surtout on est sur de ne pas y trouver ce qu'on recherche
    et encore plus si les fichiers sont volumineux

    Si je veux modifier le traitement en finesse ça risque de m'obliger à faire une couche de plus, en ne profitant pas du caractère récursif de l'instruction gci, pas vrai ?

    non tu rajouter des filtres mais tu garde le recursif. ex :  Get-ChildItem $f -Filter "*.txt" -recurse
    ou Get-ChildItem $f  -recurse | where {$_.Extension -eq ".txt"}
    ou Get-ChildItem $f  -recurse | where {$_.Extension -ne ".exe"}

    voici un exemple de traitement avec StreamReader qui est instruction la plus rapide pour la lecture de fichier :

    # FindString.ps1
    $r = $args[0]  # chaîne recherchée
    $f = $args[1]  # chemin
    $c = ""
    $hfichier = [System.IO.File]::Open($f,"Open","Read","ReadWrite")
    $stream = new-object System.IO.StreamReader($hfichier)
    $ligne = $stream.ReadLine()
    while ($ligne -ne $null) {
        if ($ligne -match $r) {
            "========$f====================="
            $ligne
            "==============================="
            }
        else {
            $f = $f
            }
        $ligne = $stream.ReadLine()
        }
    $stream.Close()


    • Modifié 6ratgus mardi 5 mars 2019 08:46
    • Marqué comme réponse Gloops mardi 5 mars 2019 09:50
    mardi 5 mars 2019 08:43

  • Si je restreins la cible à un type de fichiers, il peut y avoir des grosses bêtes à côté (style dll ou exe) ça ne ralentira pas le traitement, pas vrai ?

    ouvrir un fichier inutile est toujours une perte de temps pour des fichiers comme les exe,
    surtout on est sur de ne pas y trouver ce qu'on recherche
    et encore plus si les fichiers sont volumineux

    C'est un peu de ça que je me méfie, mais dans ce cas à quoi sert le paramètre -Include ?.


    Si je veux modifier le traitement en finesse ça risque de m'obliger à faire une couche de plus, en ne profitant pas du caractère récursif de l'instruction gci, pas vrai ?

    non tu rajouter des filtres mais tu garde le recursif. ex :  Get-ChildItem $f -Filter "*.txt" -recurse
    ou Get-ChildItem $f  -recurse | where {$_.Extension -eq ".txt"}
    ou Get-ChildItem $f  -recurse | where {$_.Extension -ne ".exe"}

    voici un exemple de traitement avec StreamReader qui est instruction la plus rapide pour la lecture de fichier :

    # FindString.ps1
    $r = $args[0]  # chaîne recherchée
    $f = $args[1]  # chemin
    $c = ""
    $hfichier = [System.IO.File]::Open($f,"Open","Read","ReadWrite")
    $stream = new-object System.IO.StreamReader($hfichier)
    $ligne = $stream.ReadLine()
    while ($ligne -ne $null) {
        if ($ligne -match $r) {
            "========$f====================="
            $ligne
            "==============================="
            }
        else {
            $f = $f
            }
        $ligne = $stream.ReadLine()
        }
    $stream.Close()

    Ah oui, tout simplement ...

    Bon, je vais voir, merci.

    mardi 5 mars 2019 08:59
  • Ça va effectivement beaucoup plus vite comme ça : -match a moins de texte à parcourir, et ça lui prenait du temps de parcourir tout le fichier.

    En définitive, lire toutes les lignes même pour ne rien en faire va plus vite.

    J'ai ajouté un intitulé "fin de traitement" pour chaque fichier. Comme ça, je me suis aperçu que là où on attend le plus, c'est pour passer d'un fichier à un autre. Ça se passe donc au niveau de Get-ChildItem.

    Je n'ai pas regardé en détail, mais il se pourrait qu'Angular nécessite beaucoup plus de fichiers, et que ça prenne un peu de temps, pour chacun, même sans l'ouvrir, de vérifier si il correspond au masque ou non. Mais quand même pas autant que ce que prenait -match pour chercher une chaîne dans tout le fichier.

    Par ailleurs, j'ai deux projets ouverts en Visual Studio. Ces deux projets ont été traités par le script, mais ça a pris un petit peu plus de temps que pour les autres.

    Merci pour ces précieux conseils.

    mardi 5 mars 2019 09:50