nikilas21
Goto Top

PowerShell Skript zum Auslesen von PDF und anschließendem Löschen des gesamten Ordners

Hi Leute,

kennt jemand von euch einen guten Ansatz, mit welchem ich ein Skript schreiben kann, welches folgendermaßen funktionieren soll:

Rahmenbedingungen: Es liegen mehrere Ordner vor. In jedem Ordner befindet sich eine PDF Datei, welche eine Adressangabe enthält. Die PDF mit der Straße "Beispiel" sollen mitsamt ihrem zugrundelegenden Ordner gelöscht werden.

  • Das Skript wird gestartet
  • Es öffnet der Reihe nach jeden Ordner im Pfad
  • Es erkennt die jeweiligen PDF- Dateien im Ordner und überprüft diese mittels "itextsharp" auf ihren Inhalt
  • Sollte der Inhalt dem Muster entsprechen, so wird der gesamte Ordner gelöscht.

Eventuell hat einer von euch bereits etwas derartiges gemacht und kann mir helfen.

Vielen Dank für mögliche Antworten und für eure Zeit!

MfG

Niklas

Content-ID: 588539

Url: https://administrator.de/contentid/588539

Ausgedruckt am: 22.11.2024 um 08:11 Uhr

144705
144705 17.07.2020 aktualisiert um 13:26:45 Uhr
Goto Top
So wie ich sehe hast du doch schon eine passende Vorlage vorliegen
Powerhellskript zum Auslesen von Kundennummern aus diversen PDFs, mit anschließender Umbenennung der Datei
Ob nun umbenennen oder Ordner löschen sollte ja kein Hexenwerk sein das anzupassen (Umbenennen halt einfach durch Ordner des aktuellen PDFs löschen tauschen). Vergleiche machst du mit -like oder -match je nach Gusto ob mit Wildcard oder Regex.
colinardo
Lösung colinardo 20.07.2020, aktualisiert am 26.04.2023 um 16:24:34 Uhr
Goto Top
Servus Niklas,
back-to-topStandard-Variante:
# ------------------------------------------------------
# Pfad in dem die PDFs liegen
$pdfquelle = "$PSScriptRoot\pdf"  
# Suchbegriff
$searchterm = 'Musterstraße 7'  
# ------------------------------------------------------

# Mindestens PS 3.0 erforderlich
if ($PSVersionTable.PSVersion.Major -lt 3){write-host "ERROR: Minimum Powershell Version 3.0 is required!" -F Yellow; return}    

# Funktion zum Laden des iTextSharp Assemblies
function Load-iTextLibrary {
    if($psscriptroot -ne ''){  
        $localpath = join-path $psscriptroot 'itextsharp.dll'  
    }else{
        $localpath = join-path $env:TEMP 'itextsharp.dll'  
    }
    $zip = $null;$tmp = ''  
    try{
        if(!(Test-Path $localpath)){
            Add-Type -A System.IO.Compression.FileSystem
            $tmp = "$env:TEMP\$([IO.Path]::GetRandomFileName())"  
            write-host "Downloading and extracting required 'iTextSharp.dll' ... " -F Green -NoNewline  

            (New-Object System.Net.WebClient).DownloadFile('https://www.nuget.org/api/v2/package/iTextSharp/5.5.13.1', $tmp)  
            $zip = [System.IO.Compression.ZipFile]::OpenRead($tmp)
            $zip.Entries | ?{$_.Fullname -eq 'lib/itextsharp.dll'} | %{  
                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_,$localpath)
            }
            write-host "OK" -F Green   
        }
        if (Get-Item $localpath -Stream zone.identifier -ea SilentlyContinue){
            Unblock-File -Path $localpath
        }
        Add-Type -Path $localpath
    }catch{
        throw "Error: $($_.Exception.Message)"  
    }finally{
        if ($zip){$zip.Dispose()}
        if ($tmp -ne ''){del $tmp -Force -EA SilentlyContinue}  
    }
}
# iText Library laden
Load-iTextLibrary

# auch geschütze PDFs öffnen aktivieren
[iTextSharp.text.pdf.PdfReader]::unethicalreading = $true

ls $pdfquelle -Directory -Recurse | ?{
    $result = $false
    foreach($pdf in (ls $_.Fullname -Filter *.pdf -File)){
        $reader = $null  
        try {
            $reader = New-Object iTextSharp.text.pdf.PdfReader $pdf.Fullname
            for($i = 1 ;$i -le $reader.NumberOfPages;$i++){
                if ([iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($reader,$i) -like "*$searchterm*"){  
                   $result = $true
                   break
                }
            }
        }catch{
            $result = $false
        }finally{
            if($reader){$reader.Dispose()}
        }
        if($result){break}
    }
    $result
} | sort {$_.Fullname.length} -Desc | del -Force -Recurse -Verbose

oder um das ganze bei großen Strukturen erheblich zu beschleunigen noch die Multithreading-Variante die die Verzeichnisse parallel verarbeitet (In Zeile 92 lässt sich mit dem Parameter -ThrottelLimit die Anzahl der zu nutzenden RunSpaces festlegen).

back-to-topMultithreading-Variante
# ------------------------------------------------------
# Pfad in dem die PDFs liegen
$pdfquelle = "$PSScriptRoot\pdf"  
# Suchbegriff
$searchterm = 'Musterstraße 7'  
# ------------------------------------------------------

# Mindestens PS 3.0 erforderlich
if ($PSVersionTable.PSVersion.Major -lt 3){write-host "ERROR: Minimum Powershell Version 3.0 is required!" -F Yellow; return}    

# Funktion zum Laden des iTextSharp Assemblies
function Load-iTextLibrary {
    if($psscriptroot -ne ''){  
        $localpath = join-path $psscriptroot 'itextsharp.dll'  
    }else{
        $localpath = join-path $env:TEMP 'itextsharp.dll'  
    }
    $zip = $null;$tmp = ''  
    try{
        if(!(Test-Path $localpath)){
            Add-Type -A System.IO.Compression.FileSystem
            $tmp = "$env:TEMP\$([IO.Path]::GetRandomFileName())"  
            write-host "Downloading and extracting required 'iTextSharp.dll' ... " -F Green -NoNewline  

            (New-Object System.Net.WebClient).DownloadFile('https://www.nuget.org/api/v2/package/iTextSharp/5.5.13.1', $tmp)  
            $zip = [System.IO.Compression.ZipFile]::OpenRead($tmp)
            $zip.Entries | ?{$_.Fullname -eq 'lib/itextsharp.dll'} | %{  
                [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_,$localpath)
            }
            write-host "OK" -F Green   
        }
        if (Get-Item $localpath -Stream zone.identifier -ea SilentlyContinue){
            Unblock-File -Path $localpath
        }
        Add-Type -Path $localpath
    }catch{
        throw "Error: $($_.Exception.Message)"  
    }finally{
        if ($zip){$zip.Dispose()}
        if ($tmp -ne ''){del $tmp -Force -EA SilentlyContinue}  
    }
}
# iText Library laden
Load-iTextLibrary

# auch geschütze PDFs öffnen aktivieren
[iTextSharp.text.pdf.PdfReader]::unethicalreading = $true

# Funktion zum beschleunigen vom Skriptblocks (runspaces mnultithreading)
function %% {
    [CmdletBinding()]
    param(
        [parameter(mandatory=$true,ValueFromPipeline=$true)][ValidateNotNullOrEmpty()][object[]]$InputObject,
        [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][scriptblock]$Process,
        [parameter(mandatory=$false)][ValidateNotNullOrEmpty()][int]$ThrottleLimit = [System.Environment]::ProcessorCount,
        [parameter(mandatory=$true)][ValidateNotNullOrEmpty()][switch]$showprogress
        
    )
    begin{
        $rspool = [runspacefactory]::CreateRunspacePool(1,$ThrottleLimit)
        $rspool.ApartmentState = 'STA'  
        $rspool.Open()
        $jobs = New-Object System.Collections.ArrayList
        $objects = New-Object System.Collections.ArrayList
    }
    process{
        $InputObject | %{[void]$objects.Add($_)}
    }
    end{
        foreach ($obj in $objects){
            $ps = [Powershell]::Create()
            $ps.RunspacePool = $rspool
            [void]$ps.AddScript($Process).AddParameter('_',$obj)  
            $job = $ps.BeginInvoke()
            [void]$jobs.Add(([pscustomobject]@{Handle = $job; Powershell = $ps}))
        }

        write-verbose "Waiting for all jobs to complete."  
        while(($jobs | ?{!$_.Handle.IsCompleted})){
            if ($showprogress.IsPresent){
                $completed = ($jobs | ?{$_.Handle.IsCompleted}).Count
                Write-Progress -Activity $PSCmdlet.MyInvocation.InvocationName -Status "Pinging a total of $($objects.Count) hosts." -PercentComplete (($completed / $objects.Count) * 100) -CurrentOperation "Completed $completed from $($objects.Count)."  
            }
        }
        # get results of jobs
        $results = $jobs | %{
            $_.Powershell.EndInvoke($_.handle)
            $_.Powershell.Dispose()
        }
        # cleanup
        $rspool.Close();$rspool.Dispose()
        $results
    }
}


ls $pdfquelle -Directory -Recurse | %% -ThrottleLimit 8 -showprogress -Process {
    param($_)
    $result = $false
    foreach($pdf in (ls $_.Fullname -Filter *.pdf -File)){
        $reader = $null  
        try {
            $reader = New-Object iTextSharp.text.pdf.PdfReader $pdf.Fullname
            for($i = 1 ;$i -le $reader.NumberOfPages;$i++){
                if ([iTextSharp.text.pdf.parser.PdfTextExtractor]::GetTextFromPage($reader,$i) -like "*$searchterm*"){  
                   $result = $true
                   break
                }
            }
        }catch{
            $result = $false
        }finally{
            if($reader){$reader.Dispose()}
        }
        if($result){
            $pdf.Directory
            break
        }
    }

} | sort {$_.Fullname.length} -Desc | del -Force -Recurse -Verbose
Code ist bei beiden Varianten etwas länger da eine Funktion zum automatischen Herunterladen und einbinden der itextsharp.dll enthalten ist, damit jeder es auch ausprobieren kann ohne sich erst die Bibliothek separat besorgen zu müssen.

Viel Spaß
Grüße Uwe