Parcourez les fichiers d'un répertoire à l'aide de PowerShell

243

Comment puis-je changer le code suivant pour regarder tous les fichiers .log dans le répertoire et pas seulement le seul fichier?

J'ai besoin de parcourir tous les fichiers et de supprimer toutes les lignes qui ne contiennent pas "step4" ou "step9". Actuellement, cela va créer un nouveau fichier, mais je ne sais pas comment utiliser la for eachboucle ici (débutant).

Les fichiers réels sont nommés comme ceci: 2013 09 03 00_01_29.log . Je voudrais que les fichiers de sortie les écrasent, ou aient le même nom, ajouté avec "out".

$In = "C:\Users\gerhardl\Documents\My Received Files\Test_In.log"
$Out = "C:\Users\gerhardl\Documents\My Received Files\Test_Out.log"
$Files = "C:\Users\gerhardl\Documents\My Received Files\"

Get-Content $In | Where-Object {$_ -match 'step4' -or $_ -match 'step9'} | `
Set-Content $Out
user2725402
la source

Réponses:

363

Essayez ceci:

Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files" -Filter *.log | 
Foreach-Object {
    $content = Get-Content $_.FullName

    #filter and save content to the original file
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content $_.FullName

    #filter and save content to a new file 
    $content | Where-Object {$_ -match 'step[49]'} | Set-Content ($_.BaseName + '_out.log')
}
Shay Levy
la source
Merci. La partie BaseName ne fonctionne pas (version 1) - mais j'ai réussi en créant d'abord une sauvegarde du fichier complet puis en apportant la modification au fichier d'origine.
user2725402
6
Pour v1, vous pouvez utiliser ce qui suit pour extraire le nom de base: [io.path] :: GetFileNameWithoutExtension ($ name)
Shay Levy
Si je remplace BaseNamepar, FullNamej'obtiens ce que je veux.
M--
78

Pour obtenir le contenu d'un répertoire, vous pouvez utiliser

$files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\"

Ensuite, vous pouvez également parcourir cette variable:

for ($i=0; $i -lt $files.Count; $i++) {
    $outfile = $files[$i].FullName + "out" 
    Get-Content $files[$i].FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}

Un moyen encore plus simple de mettre cela en place est la foreachboucle (grâce à @Soapy et @MarkSchultheiss):

foreach ($f in $files){
    $outfile = $f.FullName + "out" 
    Get-Content $f.FullName | Where-Object { ($_ -match 'step4' -or $_ -match 'step9') } | Set-Content $outfile
}
PVitt
la source
Cela crée un fichier de sortie nommé "out.log". Comment puis-je créer un fichier de sortie distinct pour chaque fichier d'entrée?
user2725402
@ user2725402 J'ai ajouté un fichier de sortie dépendant de l'entrée nommé <nom du fichier d'entrée> out
PVitt
Je ne sais pas ce que je fais mal, mais cela ne fonctionne pas - Je n'ai maintenant aucun fichier de sortie (et aucune erreur): $files = Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\" $files | Where-Object { $outFile = $_.Name + "out" Get-Content $_.FullName | Where-Object { $_ -match 'step4' -or $_ -match 'step9' } | Set-Content $outFile }
user2725402
2
Vous pouvez aussi faireforeach ($f in Get-ChildItem "C:\Users\gerhardl\Documents\My Received Files\") { ... }
Soapy
1
ou utiliserForEach ($f in $files){...}
Mark Schultheiss
31

Si vous avez besoin de boucler récursivement dans un répertoire pour un type de fichier particulier, utilisez la commande ci-dessous, qui filtre tous les fichiers de doctype fichier

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc

Si vous devez effectuer le filtrage sur plusieurs types, utilisez la commande ci-dessous.

$fileNames = Get-ChildItem -Path $scriptPath -Recurse -Include *.doc,*.pdf

Maintenant, les $fileNamesvariables agissent comme un tableau à partir duquel vous pouvez boucler et appliquer votre logique métier.

Sarath Avanavu
la source
Ce qui m'a dérangé, c'est l'omission de fichiers cachés et / ou système. Pour les voir également, vous devez utiliser le -Forceparamètre Get-ChildItem. Voir son doc sur docs.microsoft.com/en-us/powershell/module/… .
til_b
-6

Les autres réponses sont excellentes, je veux juste ajouter ... une approche différente utilisable dans PowerShell: installez les utilitaires GNUWin32 et utilisez grep pour afficher les lignes / rediriger la sortie vers le fichier http://gnuwin32.sourceforge.net/

Cela écrase le nouveau fichier à chaque fois:

grep "step[49]" logIn.log > logOut.log 

Cela ajoute la sortie du journal, au cas où vous écraser le fichier logIn et que vous souhaitez conserver les données:

grep "step[49]" logIn.log >> logOut.log 

Remarque: pour pouvoir utiliser les utilitaires GNUWin32 globalement, vous devez ajouter le dossier bin à votre chemin système.

user1628658
la source
18
Cette question a été identifiée comme PowerShell, pas Unix
SteveC
2
Oui. Évidemment. Ma décision était assez simple: vous pouvez utiliser les utilitaires GNUWin32 dans Windows, vous pouvez donc utiliser facilement les outils * nix dans Powershell. Travaux. Personne n'a jamais dit que la réponse devait être entièrement originaire de Powershell. Et même s'ils l'ont fait, vous pouvez toujours appeler Win32 Utils directement depuis Powershell. AFAIK utilisant tout ce qui est disponible et compatible n'est pas vraiment une mauvaise chose.
user1628658
2
J'aurais modifié mon commentaire précédent, mais j'ai dépassé la limite de 5 minutes: SteveC: Êtes-vous en train de dire que l'incorporation d'outils GNU qui fonctionnent bien sous Windows défie en quelque sorte Powershell? C’est une chose. Je comprends que travailler sur Powershell pourrait être plus productif à court terme. À long terme, l'expansion des possibilités a en fait plus de mérite. Vous ajoutez plus d'options et travaillez entièrement dans Windows et Powershell sans émulateurs Linux comme Cygwin. Donc, même si je comprends votre réservation, je ne suis pas d'accord.
user1628658
5
La question portait sur la recherche dans PowerShell, et non sur la multitude d'autres langues pouvant être utilisées.
SteveC
1
Les réponses sont censées être à la question. Cette question était explicite en ce qu'elle voulait la réponse dans PowerShell. Votre réponse a été d'installer quelque chose et de l'utiliser. Vous auriez pu suggérer d'installer Ruby, etc.
SteveC