2017-03-02 1 views
1

J'ai un dossier contenant des fichiers .jpg. Je les associe avec des produits dans une base de données d'accès. Une des sources pour les produits fournit ces fichiers .jpg mais ils ne vous permettent pas de télécharger facilement seulement les images que vous utilisez actuellement. Par conséquent, j'ai trouvé un script PowerShell pour supprimer les fichiers dont je n'ai pas besoin.Powershell Script pour supprimer les fichiers ne figurant pas dans une liste avec barre de progression

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } | Remove-Item 

Crédit @ x0n Powershell script to delete files not specified in a list

Et ça fonctionne très bien! mais le problème est que cela prend une éternité et j'ai plus de 180 000 articles à rechercher et à supprimer. Donc, je voulais faire une barre de progression qui me permettrait de savoir jusqu'où j'avais traversé le processus.

Ainsi, après un peu de recherche, je trouve un article intitulé « en utilisant la barre de progression »

Le problème est que je ne sais pas comment écraser les deux ensemble, mais je l'ai fait une tentative ici:

Cependant, cela semble prendre encore plus de temps que le script original, je ne sais pas exactement comment cela fonctionne, et je le teste quand j'ai seulement besoin de supprimer 10-15 fichiers.

Il est probable qu'il y ait quelque chose de vraiment basique qui me manque Mais j'apprécierais vraiment de vous aider à comprendre cela.

Ici, j'ai ajouté une capture d'écran:

PowerShell Console

Répondre

3

Cependant qui semble encore plus long que le script original a fait

C'est parce que vous essayez d'énumérer, filtre et supprimez les fichiers 100 fois - ce qui est évidemment inutile. Ce que vous voulez faire est calculer combien loin dans le processus de la suppression des fichiers que vous êtes, puis utilisez cela comme base pour le pourcentage que vous passez à Write-Progress. La meilleure façon de garder le nombre est probablement d'utiliser une boucle for régulière:

Note: ces deux premiers exemples sont très génériques, vont au fond pour un exemple qui prend le volume (~ 180.000 fichiers) en compte.

# Grab all the files you need to delete 
$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
$filesToDelete = Get-ChildItem M:\PhotoDirectory\PhotoFolder -Recurse | Where-Object {$exclusions -notcontains $_.Name } 

for($i = 0; $i -lt $filesToDelete.Count; $i++){ 
    # calculate progress percentage 
    $percentage = ($i + 1)/$filesToDelete.Count * 100 
    Write-Progress -Activity "Deleting Files" -Status "Deleting File #$($i+1)/$($filesToDelete.Count)" -PercentComplete $percentage 
    # delete file 
    $filesToDelete[$i] |Remove-Item 
} 
# All done 
Write-Progress -Activity "Deleting Files" -Completed 

Une autre caractéristique que vous pouvez utiliser pour indiquer un pourcentage est le volume relatif (nombre total d'octets) supprimé. Nous pouvons le faire en gardant simplement une trace de combien d'octets il faut supprimer au total, et combien nous avons supprimé jusqu'à présent:

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
$filesToDelete = Get-ChildItem M:\PhotoDirectory\PhotoFolder -Recurse | Where-Object {$exclusions -notcontains $_.Name } 
$TotalSize = ($filesToDelete |Measure-Object -Property Length -Sum).Sum 
$BytesRemoved = 0 

foreach($file in $filesToDelete){ 
    $percentage = $BytesRemoved/$TotalSize * 100 
    Write-Progress -Activity "Deleting Files" -Status "Deleted $BytesRemoved/$TotalSize bytes" -PercentComplete $percentage 
    $file |Remove-Item 
    $BytesRemoved += $file.Length 
} 
Write-Progress -Activity "Deleting Files" -Completed 

Comme le souligne @MatthewWetmore en invoquant Write-Progress chaque fois que vous supprimez un fichier va évidemment entraîner des frais généraux. Et avec 180.000 fichiers, vous n'êtes probablement pas intéressé à avoir la mise à jour de l'interface utilisateur lorsque la progression passe de 3,56325% à 3.56331%

Ce que vous pouvez faire est d'utiliser la boucle for compter par incréments de 1% de l'ensemble des éléments, puis retirez toute une gamme de fichiers à chaque itération:

[int]$hundredthStep = $filesToDelete.Count/100 
for($i = 0; $i -lt $filesToDelete.Count; $i += $hundredthStep){ 
    # calculate progress percentage 
    $percentage = ($i + 1)/$filesToDelete.Count * 100 
    Write-Progress -Activity "Deleting Files" -Status "Deleting File up to #$($i+1)/$($filesToDelete.Count)" -PercentComplete $percentage 
    # delete file 
    $filesToDelete[$i..($i + $hundredthStep - 1)] |Remove-Item 
} 
# All done 
Write-Progress -Activity "Deleting Files" -Completed 
+0

Si les fichiers à supprimer le nombre est extrêmement élevé, il bénéficiera également de ne pas écrire des progrès avec tous les fichier mais à la place tous les plusieurs. Par exemple, en divisant le nombre par 100, arrondissez à l'int proche, puis en l'utilisant comme un module contre un compteur. Par exemple. Avec 1-100 fichiers, vous allez écrire des progrès avec chaque fichier. Avec 200, tous les autres fichiers. Avec 1000, tous les 10 ... –

+0

En outre, j'ai vu récursif get-item sur un très grand arbre est super lent. J'ai eu plus de chance avec get-item -recurse -directory, puis itérativement get-item -file. J'ai écrit des variations sur ceci pour valider des VHD d'OS ou des contenus de WIM. –

+0

"C'est parce que vous essayez d'énumérer, de filtrer et de supprimer les fichiers 100 fois - ce qui est évidemment inutile." Cela prend du sens, bien sûr, cela prendrait plus de temps car j'essaye de le faire parcourir 100 fois le script entier et de me donner une barre de progression pour me dire quand cela se répète. J'aime l'option où il calcule le total des octets supprimés. Je vais essayer cela et revenir avec mes conclusions. – Liberator17

1

Vous voulez de faire quelque chose comme ça (attention ce n'est pas testé donc je l'ai mis -whatif sur la cmdlet remove que vous devriez enlever quand vous êtes heureux qu'il fonctionne correctement):

$exclusions = Get-Content C:\Users\office\Desktop\ExcludedPhotos.txt 
$files = dir -rec M:\PhotoDirectory\PhotoFolder | Where-Object {$exclusions -notcontains $_.name } 

$files | foreach-object { 
    $num += 1  
    Write-Progress -Activity "Deleting Files" -Status "$_ %" -Id 1 -PercentComplete (($num/$files.count) * 100) -CurrentOperation "Deleting File $($_.name)" 
    $_ | Remove-Item -WhatIf 
}