Syndication : Atom 1.0  RSS 2.0
Blogs des développeurs   »   Blog de Bruno Orsier

Article complet: Powershell, suppression sélective de fichiers

27/01/2010

Permalink 10:51:06, Catégories: Récapitulatif .NET, Récapitulatif Windows, PowerShell, PowerShell, 398 mots   French (FR) , Bruno Orsier

[.NET][Windows] Powershell, suppression sélective de fichiers

Voici un nouvel exemple d'utilisation de Powershell, histoire de peut-être vous donner envie de pratiquer ce shell bien utile. Dans mes tests, j'ai souvent un processus qui tourne en boucle, d'ailleurs grâce un script posté dans un billet précédent. Ce processus génère un fichier de log à chaque fois, ce qui me fait des dizaines de milliers de fichiers. Pour éviter de remplir le disque dur, je voudrais garder uniquement les fichiers de log qui présentent un intérêt, par exemple ceux qui contiennent le mot ERROR. C'est facile en PowerShell, avec un peu de pratique on peut le faire directement sur la ligne de commande :


[Suite:]


image

(le message  d'erreur vient d'un fichier en cours d'écriture)

Après avoir mis cela au point sur la ligne de commande comme ci-dessus, je met cette commande dans un fichier de script pour la réutiliser plus tard :

image

On peut noter dans le script la barre verticale, indiquant un pipeline. Le pipeline passe la sortie de la première commande (la liste de fichier résultant de dir) à la deuxième commande qui consiste en un foreach. Dans le bloc du foreach on référence l'objet courant (le fichier) avec la variable spéciale $_foreach est un alias pour ForEach-Object (et peut encore se raccourcir en "%", comme dans l'exemple ci-dessous).

Simple, non ?

Un autre exemple dans la même veine consiste à supprimer les fichiers .DATA générés par mes expériences, mais pas trop tôt afin de ne pas interférer avec les analyses en cours - j'attends donc 30 minutes par exemple. Voici un script pour faire cela (j'ai encadré en rouge le calcul sur les dates) :

image

Voilà le résultat sur la console :

image

Il restera à mieux formater le taux de génération !

Le même script sous forme de code copiable, au cas où ca vous intéresse de le récupérer :


$DELAY=60*15

$total_deleted = 0

while ($True) {
$deleted = 0
dir c:\data -recurse -include *.data | % {
if ( ((get-date)-$_.LastWriteTime).TotalMinutes -gt 30) {
del $_ ; $deleted += 1
}
}
$total_deleted += $deleted
$generation_rate = ($deleted / $DELAY) * 60

write-host (get-date), `
"total already deleted ", $total_deleted, `
" generation rate ", $generation_rate, " / minute"

Sleep -Seconds $DELAY
}





Voilà des exemples que j'aurais été bien incapable de réaliser en DOS, et qui sont très faciles à faire en PowerShell.



Et vous, quels sont les scripts qui vous simplifient la vie ?

Social Bookmarking:

                                     

Commentaires, Pingbacks:

Connectez-vous pour vous abonner à cet article:

Flux de commentaires pour cet article : Atom 1.0  RSS 2.0
Commentaire de: Laurent Dardenne [Membre]
Salut,
>>Et vous, quels sont les scripts qui vous simplifient la vie ?
J'en utilise de nombreux, par exemple celui-ci pour construire, à partir d'un référentiel svn, un fichier des révisions :
 
 #repository local 
 #La config de svn pointe par défaut sur l'URL adéquate  
cd g:\ps\add-lib  
  #Récupère une partie des logs au format XML  
svn log -r 76:111 --xml|Out-File -Encoding OEM g:\ps\temp\log.xml 
 
$res=[xml](gc g:\ps\temp\log.xml) 
 #Extrait du document XML, les informations souhaités 
$Res|foreach { $_.log.logentry }|% {$_.msg}| Out-File -Encoding default g:\ps\temp\log.txt 


Sinon pour ton premier exemple, on peut aussi éviter l'usage du Foreach, si l'affichage des noms de fichiers restant n'est pas nécessaire:
 
 #Whatif n'effectue pas le traitement, mais le simule. 
Dir *.bak|Select-String -Pattern ERROR -List -NotMatch|Del -whatif 


Permalien 27/01/2010 @ 13:28
Commentaire de: Bruno Orsier [Membre]
Merci Laurent pour l'exemple et la remarque sur l'utilisation directe de DEL : je n'aurais pas eu l'idée de faire aussi simple !
Permalien 27/01/2010 @ 17:03
Commentaire de: Laurent Dardenne [Membre]
>>je n'aurais pas eu l'idée de faire aussi simple
Le "truc" est qu'on pense souvent en procédural, et PowerShell c'est un peu comme Linq sous Dotnet, ça marche pas comme ça.
Sur le principe il n'y a pas de branchement mais plutôt des filtres.

Mais je reconnais que je prend souvent dans un premier temps cette approche autour de Foreach qui facilite l'écriture du "premier jet" d'un traitement.
Ensuite j'optimise en lisant la documentation, car on ne pas tout connaître par coeur sur un tel produit.

Je me permets de citer ces deux de posts du blog de Keith Hill, le chef projet de PSCX (open source):

Understanding ByValue Pipeline Bound Parameters
http://keithhill.spaces.live.com/Blog/cns!5A8D2641E0963A97!6158.entry

Understanding ByPropertyName Pipeline Bound Parameters
http://keithhill.spaces.live.com/Blog/cns!5A8D2641E0963A97!6130.entry

A leur lecture on comprend mieux la mécanique de liaison des paramètres dans le pipeline sous PowerShell.
Permalien 28/01/2010 @ 10:16
Commentaire de: Bruno Orsier [Membre]
Merci Laurent pour les références, si j'ai bien compris http://keithhill.spaces.live.com/Blog/cns!5A8D2641E0963A97!6130.entry, on peut assez facilement déterminer si un cmdlet accepte le pipeline en input grace à l'aide, par contre ce n'est pas trivial de savoir si tel ou tel type d'objet est accepté (il faut passer par du TraceCommand etc.). Ca correspond à mon exemple où cela ne me sautait pas aux yeux que le type AliasInfo sortant de Select-String pouvait passer directement en entrée de DEL...

Pour l'autre article, j'ai plus de mal, j'y reviendrai + tard !
Permalien 28/01/2010 @ 12:53
Commentaire de: Laurent Dardenne [Membre]
"par contre ce n'est pas trivial de savoir si tel ou tel type d'objet est accepté "
Si j'ai bien compris, tu peux faire ceci pour le savoir :
(get-help select-string -full).returnValues
(get-help Del -full).inputtypes

Ensuite le cmdlet Get-Member prend tout son sens, mais il faut tout de même connaitre les classes que l'on manipule, on aborde donc le niveau avancé du scripting sous PowerShell.
Si par exemple un des objets ou une classe contient une information utile, mais ne propose pas de nom de propriété attendu par un cmdlet, on peut utiliser Add-Member pour adapter l'objet au besoin.
C'est une conception remarquable.

Pour la liaison byValue on récupère l'objet dans son intégralité et pas une simple information telle qu'un nom du fichier par exemple.
Ce qui permet en interne d'appeler des méthodes sur l'objet récupéré, on évite ainsi de déclarer autant de paramètres qu'il y a de membres qui nous intéressent.

Enfin, on peut combiner les 2 types, byValue et byPropertyName, afin d’augmenter les possibilités de réussite lors de la liaison, sous réserve que cela ait un sens.

On peut utiliser PowerShell sans connaitre cette mécanique, mais une fois connue, on l'appréhende différemment.

Permalien 28/01/2010 @ 14:51
Commentaire de: Bruno Orsier [Membre]
OK, je commence à y voir légèrement plus clair dans ces deux types de liaisons !

Bruno
Permalien 29/01/2010 @ 13:07

Vous devez être identifié pour poster un commentaire.

Liste des blogs

Blog de Bruno Orsier

Rechercher

<  Février 2012  >
Lun Mar Mer Jeu Ven Sam Dim
    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        

Syndiquez ce blog XML

Articles :

Commentaires :

 
 
 
 
Partenaires

Hébergement Web