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

Scripts/Batch Discussion :

Comment filtrer des fichiers sur leur date de création [PowerShell]


Sujet :

Scripts/Batch

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 6
    Points
    6
    Par défaut Comment filtrer des fichiers sur leur date de création
    Bonjour,

    j'ai un problème avec un script qui doit fait la liste de fichier des fichier txt d'un jour donné, puis les compresser avec un utilitaire puis les supprimer une fois qu'il sont compresser.

    pb je n'arrive pas a faire un filtre correct sur la date de création des fichiers

    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
    $datej=Get-Date -format yyyy'_'MM'_'dd'_'
    $nomdufichier=$datej + "test.zip" 
    $fichiers=Get-Childitem c:\test\test\*.txt | where {!$_.CreationTime -lt (get-Date).Adddays(-2)}
     
     
    C:\localbin\7za465\7za.exe a c:\test\test\$nomdufichier $fichiers
     
     
        If ([System.IO.File]::Exists($dirsource + $nomdufichier))
    {
        Remove-Item $fichiers
    }
    else
    {
        [Console]::WriteLine("fichier n'exist pas");
    }
    merci de votre aide

  2. #2
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par Gusss Voir le message
    pb je n'arrive pas a faire un filtre correct sur la date de création des fichiers
    Le précédence des opérateurs fait que le not est exécuté sur la date et pas sur le test, utilise des parenthèses :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $fichiers=Get-Childitem c:\test\test\*.txt | where { !($_.CreationTime -lt (get-Date).Adddays(-2))}
    Ou en inversant le test.
    Ensuite $Fichiers est un tableau d'objet pas sûr que ton prg d'archive sache les manipuler, sinon utilise un fichier ascii contenant les noms de fichier complet (attention à l'encodage).
    Enfin ton prg d'archive peut générer une erreur, pour le savoir tu peux tester la valeur de $?.

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 6
    Points
    6
    Par défaut bien ça fonctionne
    Merci beaucoup

    encore une petite question
    si je veux maintenant avoir les fichiers texte d'une journée bien précise
    ex ceux du 28 et seulement ceux là
    je pensais quand remplacent -lt par -eq cela marcherait mais non
    pouvez vous me dire comment faire??


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Get-Childitem c:\test\test\*.txt | where { !($_.CreationTime -lt (get-Date).Adddays(-1))}

  4. #4
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Gusss
    si je veux maintenant avoir les fichiers texte d'une journée bien précise
    ex ceux du 28 et seulement ceux là
    Comme une journée à 24 heures ton approche ne fonctionnera pas, -eq ne peut se faire que sur le jour ou sur une date à une heure précise :
    Mais là il faut aussi tester l'année et le mois, tu peux aussi tester sur un interval de dates.
    Je te laisse regarder la doc de la classe DateTime.

    Tu peux trouver une solution simple, ensuite si tu veux effectuer ce type de recherche sur l'intégralité d'un HD il te faudra tester + solutions.

  5. #5
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Après qq essais le mieux est peut être d'utiliser un test sur une chaîne de caractères :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Measure-Command {Get-Childitem "$pwd"|% {$current=$_.CreationTime;$_}|
     Where {($current.Year -eq 2009) -and ($Current.Month -eq 12) -and 
    ($current.Day -eq 28)}}
     
    Get-Childitem "$pwd"|
     Where {"{0:dd/MM/yyyy}" -f $_.CreationTime -eq "28/12/2009"}
    Pour rechercher plusieurs dates et seulement celles-ci, on peut utiliser une expression régulière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Get-Childitem "$pwd"|
     Where { $_.CreationTime -match "(^12/28/2009|^12/27/2009)"}
    Mais ici on utilise par défaut la culture US, il faut inverser le jour et le mois, et PowerShell converti automatique le DateTime en String.
    [edit]
    Pour rechercher sur une étendue de date :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     #Les fichiers du 15 octobre 0h0:0 inclus au 31 octobre 23h59:59 inclus
    [datetime]$beginDate="10/15/2009" #culture US
    $endDate=([datetime]"10/31/2009").AddMilliseconds((((24*60)*60)*1000)-1)
     #ou 
     #$endDate=([datetime]"11/01/2009").AddMilliseconds(-1)
    Get-Childitem "$pwd"|
     where {($_.CreationTime -ge $beginDate) -and  ($_.CreationTime -le $endDate)}

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 6
    Points : 6
    Points
    6
    Par défaut un grand Merci
    merci beaucoup
    cela va me faire gagner pas mal de temps


  7. #7
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Etant donné que le cmdlet Where-Object attend un scriptblock en tant que filtre, je me suis dit qu'un générateur de filtre pouvait être utile.
    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     #Crée le générateur de filtre 
    $Filtre= New-FilterDateFile "CreationTime"
      #Filtre les fichiers d'il y a une semaine.
    $AfterThisDate=$Filtre.AfterThisDate(-7)
    #affiche le code du scriptblock
    $AfterThisDate 
     #Exécute la recherche et vérifie le résultat
    Get-Childitem "$pwd"|Where $AfterThisDate|Select Name, "CreationTime"
    La fonction de création du générateur :
    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    Function New-FilterDateFile([String] $PropertyName="CreationTime",[switch] $Force){
    #
    # Cette fonction crée un objet générateur de filtre de recherche,
    # basé sur une propriété, de type date, de la classe System.IO.FileSystemInfo.
    #
    #Arguments :
    # $PropertyName : Nom de la propriété contenant la date concernée lors la recherche
    # Attention au respect de la casse !
    # 
    # $Force : A utiliser si la propriété référence un membre synthétique
    #
    #
    #Cette fonction renvoit un objet de type PSObject, ses membres sont :
    # Méthodes (toutes renvoient un scriptblock pouvant être utilisé avec Where-Object) :
    # 
    # ThisDate : Recherche les fichiers de la date spécifiée. Les deux opérandes sont de type String.
    # Attend un argument de type string contenant une date au format Fr de type : "28/12/2009"
    #
    # TheseDates : Recherche les fichiers des dates spécifiées. Les deux opérandes sont de type String. 
    # Attend un argument de type string contenant une regex référençant des dates au format US : "(^10/07/2009|^10/31/2009)"
    # 
    # AfterThisDate : Recherche les fichiers postérieurs ou égaux à la date spécifiée. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif ou zéro. Cf. Notes
    # 
    # BeforeThisDate : Recherche les fichiers antérieurs la date spécifiée. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif ou zéro. Cf. Notes
    #
    # LastMinutes : Recherche les fichiers agés de n minutes. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif. Cf. Notes
    # 
    # LastHours : Recherche les fichiers agés de n heures. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif. Cf. Notes
    #
    # LastMonths : Recherche les fichiers agés de n mois. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif. Cf. Notes
    # 
    # LastYears : Recherche les fichiers agés de n années. Les deux opérandes sont de type DateTime. 
    # Attend un argument de type entier, négatif. Cf. Notes
    #
    # Combine : Crée un filtre contenant plusieurs clauses combinées avec l'opérateur -or
    # Attend un argument de type tableau de scriptblock.
    # 
    # Propriétés :
    # 
    # Description : Contient le nom de la propriété utilisée dans la construction des filtres.
    # Renvoi une chaîne de caractères.
    #
    # Exemples :
    # $Filtre= New-FilterDateFile "CreationTime"
    # #Filtre les fichiers d'il y a une semaine.
    # $AfterThisDate=$Filtre.AfterThisDate(-7)
    # $AfterThisDate #affiche le code du scriptblock
    # Get-Childitem "$pwd"|Where $AfterThisDate|Select Name, "CreationTime"
    # 
    # #Filtre les fichiers créés le 25 octobre 2009 et ceux créés le 31 octobre 2009
    # $TheseDates=$Filtre.TheseDates("(^10/25/2009|^10/31/2009)")
    # Get-Childitem "$pwd"|Where $TheseDates|Select Name,"CreationTime"
    # 
    # $ThisDate=$Filtre.ThisDate("30/12/2009")
    # #Filtre les fichiers créés :
    # # Il y a une semaine, 
    # # le 25 octobre 2009 et ceux créés le 31 octobre 2009
    # $FiltrePlusieursDates=$Filtre.Combine( @($AfterThisDate, $TheseDates))
    # Get-Childitem "$pwd"|Where $FiltrePlusieursDates |Select Name,"CreationTime"
    #
    #Note:
    # Suppose lors de la recherche que la date du PC est bien le jour calendaire courant.
     
    if (!$Force)
    { 
    #Vérifie si la propriété existe et est du type Date 
    $PropertyInfo=[System.IO.FileSystemInfo].GetMember($PropertyName)
    if ($PropertyInfo.Count -eq 0)
    {Throw "La propriété $PropertyName n'existe pas dans la classe System.IO.FileSystemInfo."}
    elseif ($PropertyInfo[0].PropertyType -ne [System.DateTime])
    {Throw "La propriété $PropertyName n'est pas du type [System.DateTime]."}
    }
    # Code généré "'{0:dd/MM/yyyy}' -f `$_.CreationTime -eq '$($Args[0])'"
    # renvoi lors de l'appel {'{0:dd/MM/yyyy}' -f $_.CreationTime -eq '28/12/2009'} 
    $ThisDate="`$ExecutionContext.InvokeCommand.NewScriptBlock(`"'{0:dd/MM/yyyy}' -f ```$_."+$PropertyName+" -eq '`$(`$Args[0])'`")"
    $CodeNSB="`$ExecutionContext.InvokeCommand.NewScriptBlock(`"```$_."+$PropertyName
    # Code généré "`$_.LastWriteTime -match '$($Args[0])'"
    # renvoi lors de l'appel {$_.LastWriteTime -match "(^10/07/2009|^10/31/2009)"}
    #Convertion implicite de $PropertyName.
    $TheseDates=$CodeNSB+" -match '`$(`$Args[0])'`")"
     
    $AfterThisDate=$CodeNSB+" -ge [DateTime]::Today.Adddays(`$(`$Args[0]))`")" 
    $BeforeThisDate=$CodeNSB+" -lt [DateTime]::Today.Adddays(`$(`$Args[0]))`")"
    $LastMinutes=$CodeNSB+" -ge [DateTime]::Now.AddMinutes(`$(`$Args[0]))`")"
    $LastHours=$CodeNSB+" -ge [DateTime]::Now.AddHours(`$(`$Args[0]))`")"
    $LastMonths=$CodeNSB+" -ge [DateTime]::Now.AddMonths(`$(`$Args[0]))`")"
    $LastYears=$CodeNSB+" -ge [DateTime]::Now.AddYears(`$(`$Args[0]))`")"
    #Construction dynamique du code de création de l'objet Filtre
    $MakeFilter=@"
    New-Object PSObject|
    #Args[0] attend une string contenant une date au format Fr de type : "28/12/2009"
    Add-Member ScriptMethod ThisDate -value {$ThisDate} -Passthru|
    #Args[0] attend une string contenant une regex référençant des dates au format US : "(^10/07/2009|^10/31/2009)"
    Add-Member ScriptMethod TheseDates -value {$TheseDates} -Passthru|
    #Args[0] attend un entier négatif ou zéro. 
    Add-Member ScriptMethod AfterThisDate -value {$AfterThisDate} -Passthru|
    #Args[0] attend un entier négatif ou zéro.
    Add-Member ScriptMethod BeforeThisDate -value {$BeforeThisDate} -Passthru|
    #Args[0] attend un entier négatif. 
    Add-Member ScriptMethod LastMinutes -value {$LastMinutes} -Passthru|
    #Args[0] attend un entier négatif.
    Add-Member ScriptMethod LastHours -value {$LastHours} -Passthru|
    #Args[0] attend un entier négatif. 
    Add-Member ScriptMethod LastMonths -value {$LastMonths} -Passthru|
    #Args[0] attend un entier négatif. 
    Add-Member ScriptMethod LastYears -value {$LastYears} -Passthru|
    Add-Member ScriptMethod Combine -value { 
    `$ArraySB=`$Args[0] -as [String[]] 
    `$ArraySB=`$ArraySB|% {"(`$_)"}
    `$OldOfs=`$Ofs
    `$Ofs=" -or "
    `$sb=`$ExecutionContext.InvokeCommand.NewScriptBlock("`$ArraySB")
    `$ofs=`$OldOfs
    `$sb 
    } -Passthru| 
    Add-Member ScriptProperty Description -Value {"Générateur de filtre de recherche sur la date ($PropertyName), à utiliser avec Where-Object."} -Passthru
    "@
    #Exécution du code de création de l'objet Filtre
    Invoke-Expression $MakeFilter
    }
    Comme ce modéle de commandes, la recherche de fichier selon une date, est récurrente on peut créer une fonction spécialisée :
    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
    Function Get-FilteredFiles([String]$Path, 
                               [scriptBlock] $Filter,
                                #Répertoires uniquement
                               [Switch] $ContainersOnly,
                                #Fichiers uniquement 
                               [Switch] $NoContainersOnly) 
    {
     #Construit un modéle de commande récurrente.
     #Renvoi dans le pipeline les fichiers répondant aux critéres du filtre $filter   
      begin {
        if ($ContainersOnly -and $NoContainersOnly)
         {throw "Les paramètres `$ContainersOnly et `$NoContainersOnly sont exclusifs."}
     
        Function Valide([String]$Path){
           $Ret=$True
             #Test la validité du chemin 
           Push-Location  -StackName Valide 
           Set-location $Path  
           if ($? -eq $False)
            { $Ret=$false } 
           elseif ((Get-Location).Provider.Name -ne "FileSystem") 
            { 
              Write-Error "$Path  le chemin ne référence pas le provider FileSystem."
              $Ret=$false
            }
           Pop-Location  -StackName Valide
           return $Ret
        }
     
        Function GetFilteredFiles($Path, $Filter){
           #renvoie dans le pipe les fichiers répondant aux critéres du filtre $filter
          if ($ContainersOnly)
           { Get-Childitem $Path|Where-Object {$_.PSIsContainer -eq $true}|Where-Object $Filter} 
          elseif ($NoContainersOnly)
           { Get-Childitem $Path|Where-Object {$_.PSIsContainer -eq $false}|Where-Object $Filter}    
          else
           { Get-Childitem $Path|Where-Object $Filter}
        }  
      }
      process {
        if ($Path -and $_) 
          {throw "Impossible de coupler l'usage du pipeline avec le paramètre `$Path"}
        if ($_)
         {
           if ((Valide $_)) #Valide le path
            {GetFilteredFiles $_ $Filter} #Itére sur les fichiers du path 
         }   
      }
      end { 
       if ($Path)
        {
          if ((Valide $Path)) 
            {GetFilteredFiles $Path $Filter}
        } 
      }
    }
    Un exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    $Filtre= New-FilterDateFile "LastWriteTime"
    $AfterThisDate=$Filtre.AfterThisDate(-7)
    "pscx:\","X:\","C:\"|Get-FilteredFiles -Filter $AfterThisDate  -NoContainersOnly
     #Ou sans l'usage du générateur de filtre
    "C:\","D:\"|Get-FilteredFiles -Filter {"{0:dd/MM/yyyy}" -f $_.CreationTime -eq "28/12/2009"}  -NoContainersOnly
     #On peut ajouter des segments de pipeline à la suite de Get-FilteredFiles 
    "C:\","D:\"|Get-FilteredFiles -Filter {"{0:dd/MM/yyyy}" -f $_.CreationTime -eq "28/12/2009"} |Select Name, "CreationTime"
    C'est surement plus simple de coder des filtres en dur , mais cela reste un exercice intéressant démontrant les possibilités avancées de PowerShell.
    Fichiers attachés Fichiers attachés

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [VB.NET] Comment rechercher des fichiers sur un disque.
    Par vijeo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 04/08/2017, 11h17
  2. Réponses: 7
    Dernier message: 03/05/2012, 17h10
  3. Réponses: 1
    Dernier message: 28/01/2009, 13h58
  4. Réponses: 3
    Dernier message: 12/07/2006, 10h13
  5. Comment comparer des fichiers sur Windows?
    Par programmerPhil dans le forum Autres Logiciels
    Réponses: 9
    Dernier message: 22/02/2006, 21h47

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