PowerShell: Feinkörniges Backup in eine ZIP-Datei

17.09.2017
Bild

Vor kurzem wollte ich auf einem Windows-Server ein Verzeichnis von einer Anwendung sichern. Die Anwendung besteht aus div. Komponenten, welche alle statische Konfigurationsdateien haben. Teilweise sind das .conf, .txt, und auch vereinzelt .json. Die Dateien liegen quer verstreut in div. Unterordnern. Es ist aber auch nicht auszuschließen, das hier auch exotischere Dateien liegen.

Nun liegen in dem Verzeichnis aber auch ausführbare statische Dateien (.exe, .dll), welche ich nicht sichern möchte, da diese ja wieder relativ einfach nachinstalliert werden können. Spannend sind für mich die Konfigurations-Dateien in beliebiger Form (teilweise wurden dort Anpassungen vorgenommen).

Zusätzlich liegen in 2 Unterverzeichnissen eine Postgres-Datenbank, welche natürlich nicht dateibasiert gesichert werden soll, sondern an einer anderen Stelle bereits gesichert wird.

Nun versuchte ich mich an einem PowerShell-Skript, welches mit folgende Dinge ermöglicht:

  • Ausschluss von beliebigen Dateierweiterungen
  • Ausschluss von Unterordnern anhand ihres Namens
  • Ausschluss von Dateien, welche aktuell in Verwendung sind
  • Anlegen eines Ordners nach Datum/Uhrzeit + Rotation nach n Versionen
  • Kompression der zu sichernden Dateien in einer ZIP-Datei (im Optimalfall ohne temporäres Arbeitsverzeichnis)

An sich müsste dies relativ einfach sein, dachte ich mir. Ich versuchte mit div. Funktionen im PowerShell die Ausschlüsse zu implementieren, doch PowerShell ist hier etwas "picky". Nach einigen Stunden kam dann zum Schluss dieses Skript dabei heraus:

# FancyZIPBackup Script Version 1.0.0.1 by Michael Kirgus
# Copyright (c) 2023 Michael Kirgus
# 
# This program is free software: you can redistribute it and/or modify  
# it under the terms of the GNU General Public License as published by  
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but 
# WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License 
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

param (
    [string]$TargetDirectory = (Get-Location),
    [string[]]$ExcludedSubfolders = @(),
    [string[]]$ExcludedExtensions = @(),
    [string]$DestinationPath = "",
    [string]$DestinationZIPFile = "Backup.zip",
    [string]$BackupFolderTimestampFormat = "yyyy_MM_dd-HH_mm_ss",
    [int]$MaxBackupFolders = 0  # Number of max. versions
)

$FilesArray = New-Object -TypeName 'System.Collections.ArrayList'

function Confirm-FileInUse {
    Param (
        [parameter(Mandatory = $true)]
        [string]$FilePath
    )
    try {
        $FileHandle = [System.IO.File]::Open($FilePath, 'Open', 'Read') # Open file
        $FileHandle.Close() # Opened so now I'm closing
        $FileHandle.Dispose() # Disposing object
        return $false # File not in use
    }
    catch [System.Management.Automation.MethodException] {
        return $true # Sorry, file in use
    }
}

function ListFilesRecursively($Directory) {
    Get-ChildItem -Path $Directory | ForEach-Object {
        $Item = $_
        
        # Check if the item is a directory
        if ($Item.PSIsContainer) {
            $DirectoryName = $Item.FullName
            $DirectoryFolder = $DirectoryName.Split("\")[-1]

            # Check if the directory is in the excluded subfolders list
            if ($ExcludedSubfolders -notcontains $DirectoryFolder) {
                # Recursively go into the directory
                Write-Host "Entering $DirectoryName ..."
                ListFilesRecursively -Directory $DirectoryName
            }
        }
        else {
            $FileExtension = $Item.Extension

            # Check if the file extension is in the excluded extensions list
            if ($ExcludedExtensions -notcontains $FileExtension) {
                # Check if file is in use
                if (!(Confirm-FileInUse -FilePath $Item.FullName)) {
                    $FilesArray.Add($Item.FullName)
                    Write-Host -ForegroundColor Green "Include: " $Item.FullName
                }else{
                    Write-Host -ForegroundColor Yellow "In use, exclude: " $Item.FullName
                }
            }else{
                Write-Host -ForegroundColor Red "Excluded: " $Item.FullName
            }
        }
    }
}

function CreateBackupFolder($BasePath, $TimestampFormat) {
    $Timestamp = Get-Date -Format $TimestampFormat
    $JoinedBackupFolder = Join-Path -Path $BasePath -ChildPath $Timestamp
    Write-Host "Timestamp folder name is $Timestamp"

    if (!(Test-Path -Path $JoinedBackupFolder -PathType Container)) {
        New-Item -Path $JoinedBackupFolder -ItemType Directory
    }

    return $JoinedBackupFolder
}

# Create a backup folder with a timestamp-based name
$BackupFolder = (CreateBackupFolder -BasePath $DestinationPath -TimestampFormat $BackupFolderTimestampFormat)[0]
Write-Host "Destionation folder set to $DestinationPath"
Write-Host "Backup folder set to $BackupFolder"

# Call the function with the start directory
ListFilesRecursively -Directory $TargetDirectory

# Create a ZIP file and add files in the backup folder
if ($FilesArray.Count -gt 0) {
    $DestinationZIPFileFullPath = Join-Path -Path $BackupFolder -ChildPath $DestinationZIPFile
    
    #create zip file
    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    $ZIPFileObject = [System.IO.Compression.ZipFile]::Open(($DestinationZIPFileFullPath), [System.IO.Compression.ZipArchiveMode]::Create)

    # write entries with relative paths as names
    foreach ($fname in $FilesArray) {
        $rname = $(Resolve-Path -Path $fname -Relative) -replace '\.\\',''
        Write-Output $rname
        $zentry = $ZIPFileObject.CreateEntry($rname)
        $zentryWriter = New-Object -TypeName System.IO.BinaryWriter $zentry.Open()
        $zentryWriter.Write([System.IO.File]::ReadAllBytes($fname))
        $zentryWriter.Flush()
        $zentryWriter.Close()
    }
    # release zip file
    $ZIPFileObject.Dispose()
}

if (Test-Path -Path $DestinationZIPFileFullPath -PathType Leaf) {
    Write-Host "Backup ZIP file created: $DestinationZIPFileFullPath"

    # Remove older backup folders if the number exceeds the specified limit
    if (!$MaxBackupFolders -eq 0) {
        $OldBackupFolders = Get-ChildItem -Path $DestinationPath -Directory | Sort-Object -Property CreationTime

        while ($OldBackupFolders.Count -gt $MaxBackupFolders) {
            $OldestFolder = $OldBackupFolders[0]
            Remove-Item -Path $OldestFolder.FullName -Recurse -Force
            Write-Host "Removed old backup folder: $($OldestFolder.FullName)"
            $OldBackupFolders = Get-ChildItem -Path $DestinationPath -Directory | Sort-Object -Property CreationTime
        }
    }
    exit 0
} else {
    Write-Host "Error creating ZIP File: $DestinationZIPFileFullPath"
    exit 1
}
# SIG # Begin signature block
# MIIm1AYJKoZIhvcNAQcCoIImxTCCJsECAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUqTjEDhYhSl/GvXb+25SCGDiu
# CDKggh/mMIIFbzCCBFegAwIBAgIQSPyTtGBVlI02p8mKidaUFjANBgkqhkiG9w0B
# AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy
# MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh
# MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTIxMDUyNTAwMDAw
# MFoXDTI4MTIzMTIzNTk1OVowVjELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp
# Z28gTGltaXRlZDEtMCsGA1UEAxMkU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n
# IFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjeeUEiIE
# JHQu/xYjApKKtq42haxH1CORKz7cfeIxoFFvrISR41KKteKW3tCHYySJiv/vEpM7
# fbu2ir29BX8nm2tl06UMabG8STma8W1uquSggyfamg0rUOlLW7O4ZDakfko9qXGr
# YbNzszwLDO/bM1flvjQ345cbXf0fEj2CA3bm+z9m0pQxafptszSswXp43JJQ8mTH
# qi0Eq8Nq6uAvp6fcbtfo/9ohq0C/ue4NnsbZnpnvxt4fqQx2sycgoda6/YDnAdLv
# 64IplXCN/7sVz/7RDzaiLk8ykHRGa0c1E3cFM09jLrgt4b9lpwRrGNhx+swI8m2J
# mRCxrds+LOSqGLDGBwF1Z95t6WNjHjZ/aYm+qkU+blpfj6Fby50whjDoA7NAxg0P
# OM1nqFOI+rgwZfpvx+cdsYN0aT6sxGg7seZnM5q2COCABUhA7vaCZEao9XOwBpXy
# bGWfv1VbHJxXGsd4RnxwqpQbghesh+m2yQ6BHEDWFhcp/FycGCvqRfXvvdVnTyhe
# Be6QTHrnxvTQ/PrNPjJGEyA2igTqt6oHRpwNkzoJZplYXCmjuQymMDg80EY2NXyc
# uu7D1fkKdvp+BRtAypI16dV60bV/AK6pkKrFfwGcELEW/MxuGNxvYv6mUKe4e7id
# FT/+IAx1yCJaE5UZkADpGtXChvHjjuxf9OUCAwEAAaOCARIwggEOMB8GA1UdIwQY
# MBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1UdDgQWBBQy65Ka/zWWSC8oQEJw
# IDaRXBeF5jAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUE
# DDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEMGA1Ud
# HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj
# YXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQASv6Hvi3Sa
# mES4aUa1qyQKDKSKZ7g6gb9Fin1SB6iNH04hhTmja14tIIa/ELiueTtTzbT72ES+
# BtlcY2fUQBaHRIZyKtYyFfUSg8L54V0RQGf2QidyxSPiAjgaTCDi2wH3zUZPJqJ8
# ZsBRNraJAlTH/Fj7bADu/pimLpWhDFMpH2/YGaZPnvesCepdgsaLr4CnvYFIUoQx
# 2jLsFeSmTD1sOXPUC4U5IOCFGmjhp0g4qdE2JXfBjRkWxYhMZn0vY86Y6GnfrDyo
# XZ3JHFuu2PMvdM+4fvbXg50RlmKarkUT2n/cR/vfw1Kf5gZV6Z2M8jpiUbzsJA8p
# 1FiAhORFe1rYMIIGGjCCBAKgAwIBAgIQYh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG
# 9w0BAQwFADBWMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk
# MS0wKwYDVQQDEyRTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYw
# HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBUMQswCQYDVQQGEwJHQjEY
# MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1Ymxp
# YyBDb2RlIFNpZ25pbmcgQ0EgUjM2MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB
# igKCAYEAmyudU/o1P45gBkNqwM/1f/bIU1MYyM7TbH78WAeVF3llMwsRHgBGRmxD
# eEDIArCS2VCoVk4Y/8j6stIkmYV5Gej4NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk
# 9vT0k2oWJMJjL9G//N523hAm4jF4UjrW2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7Xw
# iunD7mBxNtecM6ytIdUlh08T2z7mJEXZD9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ
# 0arWZVeffvMr/iiIROSCzKoDmWABDRzV/UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZX
# nYvZQgWx/SXiJDRSAolRzZEZquE6cbcH747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+t
# AfiWu01TPhCr9VrkxsHC5qFNxaThTG5j4/Kc+ODD2dX/fmBECELcvzUHf9shoFvr
# n35XGf2RPaNTO2uSZ6n9otv7jElspkfK9qEATHZcodp+R4q2OIypxR//YEb3fkDn
# 3UayWW9bAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaR
# XBeF5jAdBgNVHQ4EFgQUDyrLIIcouOxvSK4rVKYpqhekzQwwDgYDVR0PAQH/BAQD
# AgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYD
# VR0gBBQwEjAGBgRVHSAAMAgGBmeBDAEEATBLBgNVHR8ERDBCMECgPqA8hjpodHRw
# Oi8vY3JsLnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RS
# NDYuY3JsMHsGCCsGAQUFBwEBBG8wbTBGBggrBgEFBQcwAoY6aHR0cDovL2NydC5z
# ZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdSb290UjQ2LnA3YzAj
# BggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEM
# BQADggIBAAb/guF3YzZue6EVIJsT/wT+mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXK
# ZDk8+Y1LoNqHrp22AKMGxQtgCivnDHFyAQ9GXTmlk7MjcgQbDCx6mn7yIawsppWk
# vfPkKaAQsiqaT9DnMWBHVNIabGqgQSGTrQWo43MOfsPynhbz2Hyxf5XWKZpRvr3d
# MapandPfYgoZ8iDL2OR3sYztgJrbG6VZ9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwF
# kvjFV3jS49ZSc4lShKK6BrPTJYs4NG1DGzmpToTnwoqZ8fAmi2XlZnuchC4NPSZa
# PATHvNIzt+z1PHo35D/f7j2pO1S8BCysQDHCbM5Mnomnq5aYcKCsdbh0czchOm8b
# kinLrYrKpii+Tk7pwL7TjRKLXkomm5D1Umds++pip8wH2cQpf93at3VDcOK4N7Ew
# oIJB0kak6pSzEu4I64U6gZs7tS/dGNSljf2OSSnRr7KWzq03zl8l75jy+hOds9TW
# SenLbjBQUGR96cFr6lEUfAIEHVC1L68Y1GGxx4/eRI82ut83axHMViw1+sVpbPxg
# 51Tbnio1lB93079WPFnYaOvfGAA0e0zcfF/M9gXr+korwQTh2Prqooq2bYNMvUoU
# KD85gnJ+t0smrWrb8dee2CvYZXD5laGtaAxOfy/VKNmwuWuAh9kcMIIGaDCCBNCg
# AwIBAgIQRje1wNVeI0JWWMzv9M3MhTANBgkqhkiG9w0BAQwFADBUMQswCQYDVQQG
# EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdv
# IFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MB4XDTIyMTIxMjAwMDAwMFoXDTI0
# MTIxMTIzNTk1OVowXDELMAkGA1UEBhMCREUxGzAZBgNVBAgMEkJhZGVuLVfDvHJ0
# dGVtYmVyZzEXMBUGA1UECgwOTWljaGFlbCBLaXJndXMxFzAVBgNVBAMMDk1pY2hh
# ZWwgS2lyZ3VzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxol96wj2
# RjHMTH/k2X2V0ipQA5U9mpZINxorT7+RrH6B3yvjCIJIws37tL9Q39qoYXHzuJ0P
# Yc+wbLQxQ89ooKpkUYVgABdwITccIC08/N4DLp+GJ2ohfivd2AtUMpbH8YfnKfSx
# mUJYCFE/YLAGb5VfeAhALDHuJ9WGf01OLZR6KJIyfsN0OHdssXHqk+CRotH1vLu3
# YUDAH2MVgKlamyrR9k6ZEPKZfs6EHWgquPqEi88dvcgtddziISsRimcf062nl2pL
# m2r7mXLsC7SupoxPu4IknMJ1HGP2QqxSdhle6WrGZYEyq4oHnrZXmSYYlrhi9pim
# MaO1kJY4WuY13gI0O3SPq23WvEWtxGFV0Rv7Ymx0IP81w+T9d6Fpy6hcxX/mpkG3
# 53uUjTrsrP+7RbACn4rHzRjGZzTQbFQ64Mepk2yfU6TpmgguojQB0fTxC6hYYpaM
# XX+K9FiAOAxOTOw4ESNJXDhu20PwHUot1n7PVak3dtDCp8xQTmc4XJinn2fnJlNa
# eDKu1a/fLnXZ7PchcQMTWAjrOelIU28ieOGUxzagw7eHOYfkFYV34rM3li4OiwfL
# yMku8Ov8v/oJdV+vH40zHOnZxQoQqccaXGw4Agi5S70BbDuroCf/pSj3z6v2JJ8s
# /Lu8qL/0Pxxexdptsi2I2fk+p9hbX+rchH0CAwEAAaOCAawwggGoMB8GA1UdIwQY
# MBaAFA8qyyCHKLjsb0iuK1SmKaoXpM0MMB0GA1UdDgQWBBQryM4N+SyYJxRZ4u9s
# Ma3PqvkPejAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAK
# BggrBgEFBQcDAzBKBgNVHSAEQzBBMDUGDCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUF
# BwIBFhdodHRwczovL3NlY3RpZ28uY29tL0NQUzAIBgZngQwBBAEwSQYDVR0fBEIw
# QDA+oDygOoY4aHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29k
# ZVNpZ25pbmdDQVIzNi5jcmwweQYIKwYBBQUHAQEEbTBrMEQGCCsGAQUFBzAChjho
# dHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NB
# UjM2LmNydDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wIQYD
# VR0RBBowGIEWZGV2ZWxvcG1lbnRAa2lyZ3VzLm5ldDANBgkqhkiG9w0BAQwFAAOC
# AYEAfim4yXOU1RfJbNlTXLDtwTsgfLB12M5gSK02zziqfAGTyJxr2n5ZYgVlV6WO
# hgya4qKV5OJGHEc2XSeVkiCa8Zh5+Kau5FUwLxtqL60TWZ2HLEsPmjB7FQVUM4Dp
# CNSiH9YM/Df/L6C9ANA/KzM3dwIsljcD58AHAh8ohRIYTeJqF/yaCCMwmKzpaQ5t
# luC+qYfgqQy5Qb0sJNgLwHzhrDtwBKbrj1P9gDdQQdLUJ8o5ONBLVeaW6l4opke5
# mvBEYhWcoa7pic0D5zwxHOMaJLCJV22KS8KwM1b6iFE5p2FWjBWGY+Czcn3juFws
# tNIhA1ZmrbcQG0TPrZQQCOlXbpuq5im0CLxRSicwEVPy1PdLclO2/pBIs26BP21a
# IEM9Hv69kFp5o9FhtKwdSuNnzNcM3tOh9HLAwhn4VeLdNhfGMOZxJf3FzB2nXn1Y
# kWBKr6UuvoOfn3vGMktgcwOyjYj2vmSUQVZUKON6OxPWf5Doi24u9vCOc9gaOkjL
# 5WfhMIIG7DCCBNSgAwIBAgIQMA9vrN1mmHR8qUY2p3gtuTANBgkqhkiG9w0BAQwF
# ADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcT
# C0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAs
# BgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN
# MTkwNTAyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjB9MQswCQYDVQQGEwJHQjEbMBkG
# A1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUg
# U3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIGwGv
# 2Sx+iJl9AZg/IJC9nIAhVJO5z6A+U++zWsB21hoEpc5Hg7XrxMxJNMvzRWW5+adk
# FiYJ+9UyUnkuyWPCE5u2hj8BBZJmbyGr1XEQeYf0RirNxFrJ29ddSU1yVg/cyeNT
# mDoqHvzOWEnTv/M5u7mkI0Ks0BXDf56iXNc48RaycNOjxN+zxXKsLgp3/A2UUrf8
# H5VzJD0BKLwPDU+zkQGObp0ndVXRFzs0IXuXAZSvf4DP0REKV4TJf1bgvUacgr6U
# nb+0ILBgfrhN9Q0/29DqhYyKVnHRLZRMyIw80xSinL0m/9NTIMdgaZtYClT0Bef9
# Maz5yIUXx7gpGaQpL0bj3duRX58/Nj4OMGcrRrc1r5a+2kxgzKi7nw0U1BjEMJh0
# giHPYla1IXMSHv2qyghYh3ekFesZVf/QOVQtJu5FGjpvzdeE8NfwKMVPZIMC1Pvi
# 3vG8Aij0bdonigbSlofe6GsO8Ft96XZpkyAcSpcsdxkrk5WYnJee647BeFbGRCXf
# BhKaBi2fA179g6JTZ8qx+o2hZMmIklnLqEbAyfKm/31X2xJ2+opBJNQb/HKlFKLU
# rUMcpEmLQTkUAx4p+hulIq6lw02C0I3aa7fb9xhAV3PwcaP7Sn1FNsH3jYL6uckN
# U4B9+rY5WDLvbxhQiddPnTO9GrWdod6VQXqngwIDAQABo4IBWjCCAVYwHwYDVR0j
# BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFBqh+GEZIA/DQXdF
# KI7RNV8GEgRVMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMG
# A1UdJQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8ESTBH
# MEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2Vy
# dGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUF
# BzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1
# c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w
# DQYJKoZIhvcNAQEMBQADggIBAG1UgaUzXRbhtVOBkXXfA3oyCy0lhBGysNsqfSoF
# 9bw7J/RaoLlJWZApbGHLtVDb4n35nwDvQMOt0+LkVvlYQc/xQuUQff+wdB+PxlwJ
# +TNe6qAcJlhc87QRD9XVw+K81Vh4v0h24URnbY+wQxAPjeT5OGK/EwHFhaNMxcyy
# UzCVpNb0llYIuM1cfwGWvnJSajtCN3wWeDmTk5SbsdyybUFtZ83Jb5A9f0VywRsj
# 1sJVhGbks8VmBvbz1kteraMrQoohkv6ob1olcGKBc2NeoLvY3NdK0z2vgwY4Eh0k
# hy3k/ALWPncEvAQ2ted3y5wujSMYuaPCRx3wXdahc1cFaJqnyTdlHb7qvNhCg0MF
# pYumCf/RoZSmTqo9CfUFbLfSZFrYKiLCS53xOV5M3kg9mzSWmglfjv33sVKRzj+J
# 9hyhtal1H3G/W0NdZT1QgW6r8NDT/LKzH7aZlib0PHmLXGTMze4nmuWgwAxyh8Fu
# TVrTHurwROYybxzrF06Uw3hlIDsPQaof6aFBnf6xuKBlKjTg3qj5PObBMLvAoGMs
# /FwWAKjQxH/qEZ0eBsambTJdtDgJK0kHqv3sMNrxpy/Pt/360KOE2See+wFmd7lW
# EOEgbsausfm2usg1XTN2jvF8IAwqd661ogKGuinutFoAsYyr4/kKyVRd1LlqdJ69
# SK6YMIIG9TCCBN2gAwIBAgIQOUwl4XygbSeoZeI72R0i1DANBgkqhkiG9w0BAQwF
# ADB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAw
# DgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNV
# BAMTHFNlY3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgQ0EwHhcNMjMwNTAzMDAwMDAw
# WhcNMzQwODAyMjM1OTU5WjBqMQswCQYDVQQGEwJHQjETMBEGA1UECBMKTWFuY2hl
# c3RlcjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDDCNTZWN0aWdv
# IFJTQSBUaW1lIFN0YW1waW5nIFNpZ25lciAjNDCCAiIwDQYJKoZIhvcNAQEBBQAD
# ggIPADCCAgoCggIBAKSTKFJLzyeHdqQpHJk4wOcO1NEc7GjLAWTkis13sHFlgryf
# /Iu7u5WY+yURjlqICWYRFFiyuiJb5vYy8V0twHqiDuDgVmTtoeWBIHIgZEFsx8MI
# +vN9Xe8hmsJ+1yzDuhGYHvzTIAhCs1+/f4hYMqsws9iMepZKGRNcrPznq+kcFi6w
# sDiVSs+FUKtnAyWhuzjpD2+pWpqRKBM1uR/zPeEkyGuxmegN77tN5T2MVAOR0Pwt
# z1UzOHoJHAfRIuBjhqe+/dKDcxIUm5pMCUa9NLzhS1B7cuBb/Rm7HzxqGXtuuy1E
# Kr48TMysigSTxleGoHM2K4GX+hubfoiH2FJ5if5udzfXu1Cf+hglTxPyXnypsSBa
# KaujQod34PRMAkjdWKVTpqOg7RmWZRUpxe0zMCXmloOBmvZgZpBYB4DNQnWs+7SR
# 0MXdAUBqtqgQ7vaNereeda/TpUsYoQyfV7BeJUeRdM11EtGcb+ReDZvsdSbu/tP1
# ki9ShejaRFEqoswAyodmQ6MbAO+itZadYq0nC/IbSsnDlEI3iCCEqIeuw7ojcnv4
# VO/4ayewhfWnQ4XYKzl021p3AtGk+vXNnD3MH65R0Hts2B0tEUJTcXTC5TWqLVIS
# 2SXP8NPQkUMS1zJ9mGzjd0HI/x8kVO9urcY+VXvxXIc6ZPFgSwVP77kv7AkTAgMB
# AAGjggGCMIIBfjAfBgNVHSMEGDAWgBQaofhhGSAPw0F3RSiO0TVfBhIEVTAdBgNV
# HQ4EFgQUAw8xyJEqk71j89FdTaQ0D9KVARgwDgYDVR0PAQH/BAQDAgbAMAwGA1Ud
# EwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwSgYDVR0gBEMwQTA1Bgwr
# BgEEAbIxAQIBAwgwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9D
# UFMwCAYGZ4EMAQQCMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwuc2VjdGln
# by5jb20vU2VjdGlnb1JTQVRpbWVTdGFtcGluZ0NBLmNybDB0BggrBgEFBQcBAQRo
# MGYwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2VjdGlnb1JT
# QVRpbWVTdGFtcGluZ0NBLmNydDAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Auc2Vj
# dGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAEybZVj64HnP7xXDMm3eM5Hrd1ji
# 673LSjx13n6UbcMixwSV32VpYRMM9gye9YkgXsGHxwMkysel8Cbf+PgxZQ3g621R
# V6aMhFIIRhwqwt7y2opF87739i7Efu347Wi/elZI6WHlmjl3vL66kWSIdf9dhRY0
# J9Ipy//tLdr/vpMM7G2iDczD8W69IZEaIwBSrZfUYngqhHmo1z2sIY9wwyR5Opfx
# DaOjW1PYqwC6WPs1gE9fKHFsGV7Cg3KQruDG2PKZ++q0kmV8B3w1RB2tWBhrYvve
# bMQKqWzTIUZw3C+NdUwjwkHQepY7w0vdzZImdHZcN6CaJJ5OX07Tjw/lE09ZRGVL
# Q2TPSPhnZ7lNv8wNsTow0KE9SK16ZeTs3+AB8LMqSjmswaT5qX010DJAoLEZKhgh
# ssh9BXEaSyc2quCYHIN158d+S4RDzUP7kJd2KhKsQMFwW5kKQPqAbZRhe8huuchn
# ZyRcUI0BIN4H9wHU+C4RzZ2D5fjKJRxEPSflsIZHKgsbhHZ9e2hPjbf3E7TtoC3u
# cw/ZELqdmSx813UfjxDElOZ+JOWVSoiMJ9aFZh35rmR2kehI/shVCu0pwx/eOKbA
# FPsyPfipg2I2yMO+AIccq/pKQhyJA9z1XHxw2V14Tu6fXiDmCWp8KwijSPUV/ARP
# 380hHHrl9Y4a1LlAMYIGWDCCBlQCAQEwaDBUMQswCQYDVQQGEwJHQjEYMBYGA1UE
# ChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2Rl
# IFNpZ25pbmcgQ0EgUjM2AhBGN7XA1V4jQlZYzO/0zcyFMAkGBSsOAwIaBQCgeDAY
# BgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3
# AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEW
# BBQBZCV9qBXWWo2gqHIZMesncimebTANBgkqhkiG9w0BAQEFAASCAgAG0ra0i56t
# Pe6uZXuuXYDpuPUIEiYJDdIMBqQorsz8owtwANHP96ugiYtw4NPw+NmbrQgZ5z/1
# soNk4R6Z5fl8tPe8y1WGXezxSxuqtfMEJooEkcSjCgONhE1R/weOHmuDyPXrvjHa
# pyTkrwEiqfRE26UFLNWQcfqfhgf3NycrpzakXXCeI4yhXBJEdZbPhlDTqGiiP95z
# Y7sEAcskHx8hmjH6oRHPOpo5zMHiuWVQv02So+Yz5zepWArtKiZ1dFkJEzH1CsJa
# T8SIlBah4dyZrVd0ozEiO+iwsCTqVj0KsvrQF4ZPQhS6Kp1MhnCOYFTPHVMkLXsP
# fHjQgWGvRfW7n2XlwGBsBuQ3li0VpEHz6t27o3XFqIJ3jeaQY2pjz9vJBlswKog9
# wHMO2C5AK+wPlcTCm/xXc41hYyi7zDrVx/4osafQU6tciGLS4FQPKGrGUj+bKBSg
# 5HmJJwbhE5sFu5linKWXKrcWCRvrwzeUODXYMHINAu/j4cgWiEHwcqNMTYVxrpgH
# /1FvsGFkbUpGPoHyRGWJJArleErqLRU1llKyENMcSxGjy20lRU8fm75Wx6waogpG
# F2ng3qm0/8nfYoIg08KICkg7xm3tZIZFc325voe9Z2+F7AdwsP4BSM3HImP2BHHo
# us0m8WGYln/l9ZlmGpnD1d4ql7g2GfVQZ6GCA0swggNHBgkqhkiG9w0BCQYxggM4
# MIIDNAIBATCBkTB9MQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5j
# aGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0
# ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUgU3RhbXBpbmcgQ0ECEDlMJeF8
# oG0nqGXiO9kdItQwDQYJYIZIAWUDBAICBQCgeTAYBgkqhkiG9w0BCQMxCwYJKoZI
# hvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yMzEwMDQxNjMwMjBaMD8GCSqGSIb3DQEJ
# BDEyBDCB/fhi5wVqvItx0BGN9caz+omQHjNWqhBAwvKlbDYpv4zuJnnF6FZu0JTF
# f0NYVZYwDQYJKoZIhvcNAQEBBQAEggIADWexRp0Wov2cZxRJPGeliH3Brbg4p5Y3
# 35FV7giOMIElImAUzNeWfTQr/eYWNI27VIcH2zvuKLS3WVAUzCRSN3v/nI3T7R6F
# IoxxsM6WBfN9tvejGo/bsMkiA+51CmgKSTCWSDolSWHTfWd6G1x+v0p7QU2gFO6L
# YQ9cl4/8T8XmgvoEMTO5ShZqffBa1LXN6zZrshK3t1cOz/H9cRZoYbMu59YRQDss
# 6syKwM9hwVHjVUDHn8cdDKf2aSgU6xxIPd1XYd6xinoYdVIpeAJSveiqXIHs39Qh
# PTHbPct+Y0OZuToXvZAYrjpO/ysE+524J82lABazUlEQvVAZT0hr7ZA3aqscgsTJ
# px6gPpO9T/qeFjrKWXFSbly5rel+0RRZRjvUPnT4bZdxui6aVkajwP7shYMLwOdY
# v+hGdYiRVnFCFR+hIEqGNGcAbnvc05mYoMkYkCVstpFfSXzmFzpGXIVC827vUW0E
# XFB12pqpRjDOoFXq8/ERCwNGtfMgXHPRjPQSssVDLM4iiBf76M53c7SQiPg+ZTqy
# 1c9oL0IqEQEfOIs7qjRa6zFsVZxoJ75Xu8JOiUL+jRxlu4pxMmPNowgkmp9EP3IY
# mEtA+K9AOJ1U4FogCd2RjYCtIK+soD/LfwpvKpk4ktGCJ51qHFESUpkSIFrwRCGU
# zFgb++4hwhI=
# SIG # End signature block

Dieses Skript hat 3 Vorteile:

  • Es können beliebig viele Unterordner beliebig viele Dateitypen ausgeschlossen werden
  • Das Skript packt die dann noch übrigen Dateien in eine ZIP-Datei direkt, ohne über ein lokales Arbeitsverzeichnis gehen zu müssen
  • Die Ordnerpfade werden in der ZIP-Datei beibehalten

 

Feedback, Verbesserungsvorschläge, weitere Ideen?

Einfach das Kontaktformular verwenden oder direkt eine E-Mail an info@kirgus.net.