web-dev-qa-db-fra.com

Fichier PowerShell ForEach $ dans $ Files

J'ai un script PowerShell qui obtient une liste de fichiers et déplace les fichiers qui répondent à des critères spécifiques. Pourquoi la boucle foreach s'exécute-t-elle même si l'objet est vide?

Je suppose que si $ i n'existait pas, il ne fonctionnerait pas. Mais s'il n'y a aucun résultat dans $ filePath, pourquoi la boucle forEach s'exécute-t-elle une fois? J'ai travaillé sur mon problème, mais je suis curieux et j'ai essayé de chercher, mais je n'ai pas pu trouver la réponse.

Pour que cela fonctionne, je vérifie simplement que $ filePath existe avant la boucle forEach.

Par exemple, si ($ filePath) {...

 $filePath = Get-ChildItem -Path $sourceDir | Where-Object {! $_.PSIsContainer -AND ($_.Name -Match "^XXX_XXX*" -OR $_.Name -Match "^YYY_XX*")}

 ForEach($i in $filePath){
     $sfName =  $i.Name
     $sfDir = $i.Directory
     $tFileName = testFile $destDir $sfName
     $sFile = $sourceDir + $sfName
     $tFile = $destDir + $tFileName

     moveFile $sFile $tFile
13
Bagger

Il s'agit d'un problème classique qui a été résolu dans PowerShell V3 IIRC. La boucle foreach de PowerShell vous permettra d'itérer sur une valeur scalaire, par exemple:

foreach ($i in 1) {$i}

C'est pratique car la collection que vous itérez peut contenir plusieurs fois 0, 1 ou N éléments, par exemple:

$files = Get-ChildItem c:\temp\*.txt
foreach ($file in $files) {$file}

Dans ce cas, Get-ChildItem Pourrait retourner 0, 1 ou N fichiers. N fichiers est génial, nous pouvons répéter cela. Cependant, s'il renvoyait 1 fichier et que vous deviez ensuite coller ce fichier dans un tableau afin de pouvoir utiliser foreach - eh bien, ce serait un peu nul. Donc foreach vous permet d'itérer sur un objet scalaire. Le problème se produit lorsque Get-ChildItem Renvoie 0 objets. Dans ce cas, un tableau vide n'est pas affecté aux fichiers $. Au lieu de cela, $ null est attribué. PowerShell considère $ null comme un scalaire et donc la boucle foreach s'exécutera une fois où la valeur itérée est $ null. Ce genre de suce. Et moi et beaucoup d'autres personnes avons dit à l'équipe très tôt, donc dans la V3, ils ont changé foreach pour ne pas itérer un scalaire si la valeur est $ null.

Une autre façon de contourner cela dans V1/V2 est de s'assurer que le cas vide génère un tableau vide au lieu de $ null. Vous pouvez le faire en utilisant une expression de tableau @(), par exemple.

$files = @(Get-ChildItem c:\temp\*.txt)
foreach ($file in $files) {$file}

Cela fonctionnera pour les fichiers 0, 1 et N. Cela fonctionne pour 0 fichier car le @() entraînera l'affectation d'un tableau vide aux fichiers $. foreach n'exécutera pas son corps lors d'une boucle sur un tableau vide.

31
Keith Hill