Question Pb avec filtre dans une variable

Plus d'informations
il y a 13 ans 9 mois #7377 par Régis LOUIS
Bonjour,

Je construis un filtre dans une variable parce que par défaut, je ne connais pas le nom des dossiers à exclure lorsque je fais un get-childitem.

La construction de la ligne qui va filtrer se fait par un get-content d'un fichier txt contenant les dossiers à exclure.

[code:1]$Fichier_Exclusions = Get-Content c:\WINDOWS\system32\WindowsPowerShell\v1.0\exclusion.txt
[string]$Exclusion_Parameter = $null
foreach ($line in $Fichier_Exclusions)
{
[string]$Traitement = $Path_App_Files + $line
$Traitement = $Traitement -replace \"\\\",\"\\\"
If (!($Exclusion_Parameter))
{
$Exclusion_Parameter = $Exclusion_Parameter + \"`$_.fullname -notmatch \" + $Traitement
}
Else
{
$Exclusion_Parameter = $Exclusion_Parameter + \" -and `$_.fullname -notmatch \" + $Traitement
}
}

$Exclusion_Parameter = $Exclusion_Parameter + \" -and `$_.PSIsContainer -notmatch `$true\"[/code:1]

Jusque là ça fonctionne bien. Il me contruit bien mon filtre comme je le souhaite

C'est ensuite que cela se complique

[code:1]Get-ChildItem -Path $Path_App_Files *.* -include * -Recurse | where {$Exclusion_Parameter} | select-object Name,LastWriteTime,Directory | Export-Csv $PathLog\Liste_Files.csv -NoTypeInformation -Encoding UTF8
[/code:1]

Le contenu de variable $Exclusion_Parameter n'est pas pris en compte et je n'ai pas de message d'erreur.

La syntaxe suivante fonctionne mais m'oblige à fixer les dossiers à exclure que je ne peux connaître à l'avance

[code:1]Get-ChildItem -Path $Path_App_Files *.* -include * -Recurse | where {$_.fullname -notmatch $Path_Exclude1 -and $_.fullname -notmatch $Path_Exclude2 -and $_.PSIsContainer -notmatch $true} | select-object Name,LastWriteTime,Directory | Export-Csv $PathLog\Liste_Files.csv -NoTypeInformation -Encoding UTF8
[/code:1]

Comment faire pour que le contenu de ma variable $Exclusion_Parameter soit prise en compte par la cmdlet Where-Object ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 9 mois #7378 par Laurent Dardenne
Salut,
rnglouis écrit:

Le contenu de variable $Exclusion_Parameter n'est pas pris en compte et je n'ai pas de message d'erreur.

Si, mais il ne fait pas ce que tu veux :
[code:1]
{$Exclusion_Parameter}
#$Exclusion_Parameter
&{$Exclusion_Parameter}
#$_.fullname -notmatch test.txt -and $_.fullname -notmatch cou pure.dat -and
#$_.PSIsContainer -notmatch $true -and $_.fullname -notmatch test.txt -and $_.fullname -notmatch cou pure.dat
[/code:1]
Tu recherches à substituer le contenu de la variable, mais tu ne fais que réémettre l'objet reçu car \"ton filtre\" n'est pas exécuté en tant que code :
[code:1]
$Exclusion_Parameter=\"Contenu renseigné\"
1|where {$Exclusion_Parameter}|gm
# TypeName: System.Int32
#...
$Exclusion_Parameter=$null
1|where {$Exclusion_Parameter}|gm
#Get-Member : Aucun objet n'a été spécifié à l'applet de commande get-member.

$Exclusion_Parameter=$false
1|where {$Exclusion_Parameter}|Write-host -fore green
#rien
$Exclusion_Parameter=$true
1|where {$Exclusion_Parameter}|Write-host -fore green
#1
$Exclusion_Parameter=$null
1|where {$Exclusion_Parameter}|Write-host -fore green
#rien
$Exclusion_Parameter=\"Contenu renseigné\"
1|where {$Exclusion_Parameter}|Write-host -fore green
#1
[/code:1]
Tu dois donc préciser ce que tu veux faire de la variable, PowerShell ne peux pas le deviner.
Avec cette approche tu dois donc construire le filtre ET le code d'interrogation.
rnglouis écrit:

Comment faire pour que le contenu de ma variable $Exclusion_Parameter soit prise en compte par la cmdlet Where-Object ?

Tu as la réponse ici :
rnglouis écrit:

Je construis un filtre dans une variable

Ton code contruit une string, si tu construis un scriptblock la suite est bien plus simple :
[code:1]
#filtre les objets de type integer
$Exclusion_Parameter='$_ -is [int]'
$Filtre=$ExecutionContext.InvokeCommand.NewScriptBlock($Exclusion_Parameter)
\"A\",1| Where $Filtre
#renvoi seulement l'objet, l'entier, 1
[/code:1]
Ensuite l'opérateur -notmatch est dédié aux expressions régulières, donc au type string, mais ne concerne pas le test de boolean :
[code:1]
`$_.PSIsContainer -notmatch `$true\"
#ceci suffit
-and `$_.PSIsContainer -and ...
[/code:1]
Enfin tu devrais placer tes noms de fichiers entre guillemets : \"c:\program file\test.txt\", ce qui t'éviteras qq suprises...

Tu peux aussi consulter ce post qui à trait à la construction de filtre dynamique.<br><br>Message édité par: Laurent Dardenne, à: 13/07/10 14:38

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 9 mois #7379 par Régis LOUIS
Merci beaucoup Laurent pour ton aide

En effet je ne savais pas comment faire pour que ma variable soit comprise comme un scriptblock

il me manquait cette ligne :

[code:1]$Filtre=$ExecutionContext.InvokeCommand.NewScriptBlock($Exclusion_Parameter)
[/code:1]

et les guillemets.


Par contre cette syntaxe ne liste que les dossiers

[code:1]-and `$_.PSIsContainer[/code:1]

Or ce que je recherche c'est l'exclusion des dossiers. Je ne cherche que la liste de tous les fichiers.

La syntaxe a priori idéale puisque la propriété est booléenne est

[code:1]-and !(`$_.PSIsContainer)[/code:1]


Confirmes tu ?<br><br>Message édité par: rnglouis, à: 13/07/10 15:50

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 9 mois #7380 par Laurent Dardenne
rnglouis écrit:

Par contre je n'ai pas compris si la syntaxe
[code:1]-and `$_.PSIsContainer[/code:1]

Le plus souvent dans les langages informatique, l'usage d'un booléen (seules deux valeurs sont possibles) dans un test ne nécessite pas de préciser d'opérateur d'égalité :
[code:1]
[boolean] $IsPsContainer=$true
if ($IsPsContainer) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#Le test réussi
$IsPsContainer=$false
if ($IsPsContainer) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue
[/code:1]
C'est une facilité d'écriture, on peut écrire comme ceci :
[code:1]
$IsPsContainer=$true
if ($IsPsContainer -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#Le test réussi
[/code:1]
On peut revoir le comportement précisé dans le post précédent :
[code:1]
$Exclusion_Parameter=\&quot;Contenu renseigné\&quot;
if ($Exclusion_Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#Le test réussi

$Exclusion_Parameter=$null
if ($Exclusion_Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue
[/code:1]
Si le contenu de la variable est à $null alors le test échoue, c'est un comportement à connaître.

Si on manipule des entiers:
[code:1]
$Parameter=3
if ($Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#Le test réussi

$Parameter=0
if ($Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue, car [int]$false = 0
[/code:1]
Ces comportements sont dus à la conversion en cas d'absence d'opérateur:
[code:1]
#$Parameter=$null
$Parameter -as [boolean]
#False

$Parameter=\&quot;Test\&quot;
$Parameter -as [boolean]
#True

$Parameter=0
$Parameter -as [boolean]
#False

$Parameter=3
$Parameter -as [boolean]
#True
[/code:1]
Mais si on précise un opérateur, on effectue alors un 'vrai test booléen' :
[code:1]
$Parameter=3
if ($Parameter -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue

$Parameter=$null
if ($Parameter -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue

$Parameter=\&quot;test\&quot;
if ($Parameter -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue

$Parameter=$null
if ($Parameter -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue, idem pour $Parameter=\&quot;\&quot;

$Parameter=0
if ($Parameter -eq $true) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue
[/code:1]
Pour résumé :
- si ta variable est typée en boolean, tu peux ne pas préciser d'opérateur.
- si ta variable n'est pas typée en boolean, tu dois préciser un opérateur pour éviter des effets de bords et faciliter la relecture.

En espérant ne pas t'avoir embrouillé.<br><br>Message édité par: Laurent Dardenne, à: 25/07/10 18:44

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 13 ans 8 mois #7454 par Laurent Dardenne
J'ajoute ceci pour garder une trace :
[code:1]
$Parameter=3
if ($true -eq $Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test réussi

$Parameter=$null
if ($true -eq $Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue

$Parameter=\&quot;test\&quot;
if ($true -eq $Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test réussi

$Parameter=$null
if ($true -eq $Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue, idem pour $Parameter=\&quot;\&quot;

$Parameter=0
if ($true -eq $Parameter) {\&quot;Le test réussi\&quot;} else {\&quot;le test échoue\&quot;}
#le test échoue
[/code:1]
Pour faciliter les choses, selon que la valeur à convertir est à gauche ou à droite de l'opérateur, le résultat différe pour
$Parameter=3 et $Parameter=\&quot;test\&quot;
Les syntaxes suivantes sont donc autorisées :
[code:1]$F=dir C:\Temp\UnFichierDeTest.Txt
$F.IsReadOnly
$F.isReadOnly=\&quot; f sd\&quot;
$F.IsReadOnly
$F.isReadOnly=$null
$F.IsReadOnly
$f.IsReadOnly=7
$f.IsReadOnly[/code:1]
Cela ne pose pas de pb !!!
:silly:

[edit]
From PowerShell.com

When you compare version strings, PowerShell will use alphanumeric algorithms, which may lead to confusing results:

[code:1]'3.4.22.12' -gt '22.1.4.34'
True
[/code:1]

You should convert the strings to a System.Version type to compare version strings right. In fact, converting the left hand value is enough because PowerShell automatically converts the right hand value to the same type:

[code:1][System.Version] '3.4.22.12' -gt '22.1.4.34'
False
[/code:1]

Message édité par: Laurent Dardenne, à: 1/09/10 16:46<br><br>Message édité par: Laurent Dardenne, à: 1/09/10 16:46

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.078 secondes
Propulsé par Kunena