# PowerShell 4.0 Script # Einfaches kopieren oder verschieben von Dateien. # Digital Data # Ludwig-Rinn-Strasse 16 # 35452 Heuchelheim # Tel.: 0641 / 202360 # E-Mail: info@didalog.de # Version 1.0 # Letzte Aktualisierung: 08.12.2014 # Mindestanforderung für dieses Skript: # Microsoft Windows XP SP3 / Server 2008 R2 SP1 -> siehe KB976932 # Microsoft .NET Framework 4.5 -> siehe KB2858728 # Microsoft PowerShell 4.0 -> siehe KB2819745 # WICHTIG: Falls sich dieses Skript nicht ausführen lässt, # muss dieser PS-Befehl noch mit administrativen Rechten ausgeführt werden: # set-executionpolicy unrestricted #Requires –Version 4.0 #----------------------------------------------------------------------------------------------------- ############################ Zusätzliche Assemblys hinzufügen bzw. laden. ############################ #----------------------------------------------------------------------------------------------------- #----------------------------------------------------------------------------------------------------- ######################################## Variablen definieren. ####################################### #----------------------------------------------------------------------------------------------------- Set-Variable -Name ScriptName -Value (($MyInvocation.MyCommand.Name) -split "\.")[0].ToString() -Scope script Set-Variable -Name ScriptPath -Value (Split-Path ($MyInvocation.MyCommand.Path)) -Scope script Set-Variable -Name ConfigFile -Value "$ScriptPath\$ScriptName`_Settings.ini" -Scope script Set-Variable -Name KonfigWerte -Value $NULL -Scope script Set-Variable -Name ZeitStempel1 -Value $(Get-Date -Format 'ddMMyyyy_HHmmss') -Scope script Set-Variable -Name Timestamp1 -Value $(Get-Date -Format 'ddMMyyyy') -Scope script Set-Variable -Name Timestamp2 -Value $(Get-Date -Format 'ddMMyyyy_HHmmss') -Scope script Set-Variable -Name Timestamp3 -Value $(Get-Date -Format 'ddMMyyyy_HHmmssffff') -Scope script Set-Variable -Name Fehler -Value $NULL -Scope local Set-Variable -Name LogDatei -Value "$ScriptName`_$ZeitStempel1.log" -Scope script Set-Variable -Name LogEintrag -Value $NULL -Scope local Set-Variable -Name LogPathListe -Value $NULL -Scope script Set-Variable -Name LogPath -Value $NULL -Scope script Set-Variable -Name LogPathEintrag -Value $NULL -Scope script Set-Variable -Name LogKeepTime -Value 60 -Scope script Set-Variable -Name FileDelayAge -Value 5 -Scope script Set-Variable -Name Item -Value $NULL -Scope local Set-Variable -Name Items -Value $NULL -Scope local Set-Variable -Name Path -Value $NULL -Scope local Set-Variable -Name PathTest -Value $NULL -Scope local Set-Variable -Name ProzessTest -Value $NULL -Scope local Set-Variable -Name VersionSeperator -Value '~' -Scope local Set-Variable -Name FileSeperator -Value '' Set-Variable -Name Sourcepath -Value $NULL -Scope local Set-Variable -Name Destinationpath -Value $NULL -Scope local #----------------------------------------------------------------------------------------------------- ####################################### Funktionen definieren. ####################################### #----------------------------------------------------------------------------------------------------- $test1 = Select-String -Path $MyInvocation.InvocationName -Pattern Func-*| select Matches write-host $test1 pause Function Func-Path-Check { <# .SYNOPSIS Function will check the given Path for existence. .DESCRIPTION Function will check the given Path for existence. If Path doesn´t exist, Function will try to create it. .REQUIREMENT General PowerShell V2 and Function "Func-Write-Logfile". .REQUIREMENT Variables Path, PathTest .VERSION 1.0 / 06.11.2014 .EXAMPLE Func-Path-Check -Path "E:\Path\to\check" .EXAMPLE Func-Path-Check -Path "E:\Path\to\create" .PARAMETER Path Give the full Path you want to check or create. #> Param ( [String]$Path ) $PathTest = Test-Path -PathType Container $Path Func-Write-Logfile -LogEintrag "Checking Path $Path for existence." IF ($PathTest -eq "True") { Func-Write-Logfile -LogEintrag "Path $Path is already existence and can be used." } ELSE { Try { Func-Write-Logfile -LogEintrag "Path $Path has to been created." New-Item -Path $Path -ItemType directory -force -ErrorAction Stop } Catch { Func-Write-Logfile -LogEintrag "ERROR: Unable to create Path." Func-Write-Logfile -LogEintrag "INFO: Maybe there is an access or rights Problem." Func-Write-Logfile -LogEintrag "Application was unplannd terminated." EXIT } } } Function Func-Write-Logfile { <# .SYNOPSIS Function will write a given String to a Logfile. .DESCRIPTION Function will write a given String to a Logfile. It will even log Error Messages. .REQUIREMENT General PowerShell V2 .REQUIREMENT Variables LogPathListe, LogPathEintrag, LogPath, Fehler, Pfad-Test .VERSION 1.0 / 06.11.2014 .EXAMPLE Func-Path-Check -Log "Write this in my Log, please." .EXAMPLE Func-Path-Check -Log "Write this Variabel $Variable in my Log, please." .PARAMETER Log Give the Sting you want to be written in the Logfile. #> Param ( [string]$LogEintrag ) # Der Fehlerindikator ($?) muss bereits zu Anfang abgefragt werden, # da er von JEDEM funktionierenden Befehl wieder auf True gesetzt wird. IF ($? -ne 'True') { Set-Variable -Name Fehler -Value 1 } IF ($LogPath -eq $NULL) { Set-Variable -Name LogPathListe -Value @($LogPathListe) Set-Variable -Name LogPathListe -Value ($LogPathListe += "$ScriptPath\Logs","$env:temp") FOREACH ($LogPathEintrag in $LogPathListe) { $PfadTest = Test-Path -PathType Container "$LogPathEintrag" Write-Host "Pfadüberprüfung: Prüfe ob LogPath bereits angelegt ist: $LogPathEintrag" IF ($PfadTest -eq "True") { Write-Host "Pfadüberprüfung: LogPath $LogPathEintrag ist bereits angelegt!" Set-Variable -Name LogPath -Value $LogPathEintrag break } ELSE { Write-Host "Pfadüberprüfung: LogPath $LogPathEintrag muss angelegt werden." New-Item -Path $LogPathEintrag -ItemType directory -force -ErrorAction SilentlyContinue | Out-Null $PfadTest = Test-Path -PathType Container $LogPathEintrag Write-Host "Pfadüberprüfung: Prüfe ob Pfad erfolgreich angelegt werden konnte." IF ($PfadTest -eq "True") { Write-Host "Pfadüberprüfung: Pfad $LogPathEintrag wurde erfolgreich angelegt." Set-Variable -Name LogPath -Value $LogPathEintrag break } ELSE { Write-Host "Pfadüberprüfung: Pfad $LogPathEintrag konnte nicht angelegt werden." Set-Variable -Name LogPath -Value $LogPathEintrag } } } } ELSEIF ($LogPath -eq $env:temp) { Write-Warning "FEHLER: LogPath nicht zugreifbar oder nicht korrekt konfiguriert!" Write-Warning "INFO: $LogPath - wird nun verwendet!" Write-Warning "Programm wird trotzdem fortgesetzt." } Set-Variable -Name LogPath -Value $LogPath -scope script Write-Host $LogEintrag Add-content $LogPath\$LogDatei -value "$(Get-Date -Format 'dd.MM.yyyy')-$(Get-Date -Format 'HH:mm:ss'): $LogEintrag" IF ($Fehler -eq 1) { Write-Host "Fehlermeldung: $error" Add-content $LogPath\$LogDatei -value "$(Get-Date -Format 'dd.MM.yyyy')-$(Get-Date -Format 'HH:mm:ss'): Fehlermeldung: $error" # Setze Fehlerspeicher zurück $error.clear() } } # Funktion um eine Textdatei (ASCII), komplett einzulesen. Function Func-ReadConfigFile { Param ( [String]$ConfigFile ) Write-Host "" Write-Host "Prüfe ob Konfigurationsdatei: $ConfigFile vorhanden ist." $DateiTest = Test-Path -PathType Leaf $ConfigFile IF ($DateiTest -eq "True") { Write-Host "Konfigurationsdatei ist vorhanden, fahre fort." } ELSE { Func-Write-Logfile -LogEintrag "FEHLER: Konfigurationsdatei ist nicht vorhanden!" Func-Write-Logfile -LogEintrag "Programm wird ungeplant beendet." EXIT } Write-Host "Konfigurationsdatei wird nun eingelesen." Set-Variable -Name KonfigWerte -Value (Select-String -path $ConfigFile -pattern "=" | where {-not($_-match "#")}) IF ($KonfigWerte -eq $Null) { Write-Host "Keine gültigen Werte in Konfigurationsdatei erkannt!" } ELSE { Write-Host "Es wurden"$KonfigWerte.count"Zeilen aus der Konfigurationsdatei eingelesen." #Write-Host "Folgende Werte wurden eingelesen:" #Write-Host "$KonfigWerte" } Set-Variable -Name KonfigWerte -Value $KonfigWerte -Scope script } # Funktion um eine Textdatei (ASCII), komplett einzulesen. # Gibt immer nur einen Wert zurück! Function Func-ReadConfigValue { Param ( [String]$KonfigBezeichner ) $Items = ($KonfigWerte.line | select-string -pattern "$KonfigBezeichner") IF ($Items -eq $NULL) { Write-Host "Der gesuchte Bezeichner ($KonfigBezeichner) konnte nicht gefunden werden!" Write-Host "Standardwert wird verwendet!" $KonfigBezeichner = (Get-Variable -Name $KonfigBezeichner -ValueOnly) return $KonfigBezeichner } ELSEIF ($Items.GetType() -like "*Microsoft.PowerShell.Commands.MatchInfo*" -or $Funde.GetType() -like "*String*") { $Items = ($Items -split "=") $Items = @($Items) $Items = $Items[1] $Items = ($Items.TrimStart()) $Items = ($Items.TrimEnd()) return $Items } ELSEIF ($Items -is [Array]) { return $Items } } Function Func-Dateien-zusammensuchen { Param ( [String]$SuchPath, [Array]$SuchWhiteList, [Array]$SuchBlackList ) Set-Variable -Name SuchWhiteList -Value ($SuchWhiteList -Replace " ","") Set-Variable -Name SuchWhiteList -Value ($SuchWhiteList -Split ",") Set-Variable -Name SuchWhiteList -Value ($SuchWhiteList -Split ";") Set-Variable -Name SuchBlackList -Value ($SuchBlackList -Replace " ","") Set-Variable -Name SuchBlackList -Value ($SuchBlackList -Split ",") Set-Variable -Name SuchBlackList -Value ($SuchBlackList -Split ";") $Items = Get-ChildItem -Path "$SuchPath" -include $SuchWhiteList -exclude $SuchBlackList -Recurse IF ($Items -eq $NULL) { Func-Write-Logfile -LogEintrag "Could not find any File(s) in Path: $SuchPath (regard on White and Black Lists)." } ELSE { Func-Write-Logfile -LogEintrag "Could find some File(s) in Path: $SuchPath (regard on White and Black Lists) ..." FOREACH ($Item in $Items) { Func-Write-Logfile -LogEintrag "...one Found is: $Item" } return $Items } } Function Func-File-copy-or-move { <# .SYNOPSIS Function will copy or move File(s). .DESCRIPTION Function will copy or move File(s). If File already exists in target Path new File will get a Version ~2. .REQUIREMENT General PowerShell V2 .REQUIREMENT Variables Datei, Datei1, DateiName, DateiEndung, DateiTest, DateiVersion,ZielPath, MoveorCopy, SourcePath .VERSION 1.2 / 15.09.2015 .EXAMPLE Func-Dateien-Versionieren -Datei "E:\Quellpfad\Test.txt" -ZielPath "E:\Zielpfad" -MoveorCopy move .EXAMPLE Func-Dateien-Versionieren -Datei "E:\Quellpfad\Test.txt" -ZielPath "E:\Zielpfad" -MoveorCopy copy .PARAMETER $Datei Give the full Path and Filename to one File. .PARAMETER $ZielPath Give the Target path you want to move or copy the specified File. .PARAMETER $MoveOrCopy Give this Parameter to determ a copy or a move Order. #> Param ( [String]$filename_and_path, [String]$file_targetpath, [String]$move_or_copy, [String]$newfilename, [String]$newfilename_prefix, [String]$newfilename_suffix ) Set-Variable -Name SourcePath -Value (split-path "$filename_and_path") Set-Variable -Name Filename -Value (split-path "$filename_and_path" -Leaf) IF (($MoveorCopy -ne 'move') -and ($MoveorCopy -ne 'copy')) { Func-Write-Logfile -LogEintrag "ERROR: Wrong Function call." Func-Write-Logfile -LogEintrag "INFO: Parameter move_or_copy accepts only 'move' or 'copy'." Func-Write-Logfile -LogEintrag "Application will use the copy Order by default." Set-Variable -Name move_Or_copy -Value copy -Scope local } IF (($VersionSeperator -eq $null) -or ($VersionSeperator -eq '')) { Func-Write-Logfile -LogEintrag "ERROR: Wrong Function call." Func-Write-Logfile -LogEintrag "INFO: Variable VersionSeperator is not valid." Func-Write-Logfile -LogEintrag "Application was unplannd terminated." EXIT } IF ($newfilename -gt "") { Func-Write-Logfile -LogEintrag "New Filename will replace the old one." Set-Variable -Name Filename -Value $newfilename -Scope local } IF ($newfilename_prefix -gt "") { Func-Write-Logfile -LogEintrag "New prefix has been set for file." } IF ($newfilename_suffix -gt "") { Func-Write-Logfile -LogEintrag "New suffix has been set for file." } # Set-Variable -Name Filename -Value ($newfilename_prefix + $filename + $newfilename_suffix) # Does file already exist in the target directory? Set-Variable -Name Filetest -Value (Test-Path -PathType Leaf "$file_targetpath\$Filename") IF ($Filetest -eq 'True') { Func-Write-Logfile -LogEintrag "" Func-Write-Logfile -LogEintrag "The File already exists in the Target Directory, starting Version Check." Set-Variable -Name $FileNameSplit -Value ($Filename -split "$VersionSeperator") Set-Variable -Name $FileVersion -Value $FileNameSplit[1] # Has the new file already a Version tag? IF ($FileVersion -eq $NULL) { Func-Write-Logfile -LogEintrag "Sourcefile includes no VersionSeperator." Set-Variable -Name FileNameSplit -Value ($Filename -split "\.") Set-Variable -Name FileName -Value $FileNameSplit[0] Set-Variable -Name FileExtension -Value $FileNameSplit[1] # To skip Version ~1. $FileVersion++ } ELSE { Func-Write-Logfile -LogEintrag "Sourcefile includes VersionSeperator." Set-Variable -Name FileNameSplit -Value ($FileNameSplit -split "\.") Set-Variable -Name FileName -Value $FilenameSplit[0] Set-Variable -Name FileVersion -Value $FilenameSplit[1] Set-Variable -Name FileExtension -Value $FilenameSplit[2] # To convert String Value to Integer. $DateiVersion = $DateiVersion -as [Int] } DO { Write-Host "DEBUG Info: Count file version:" $FileVersion; $FileVersion++ } while ( ($Filetest = Test-Path -Path "$file_targetpath\$FileName$VersionSeperator$FileVersion.$FileExtension") -eq 'True' ) # code block for the copy or move process Try { Set-Variable -Name FileTemp -Value (Copy-Item -Path "$filename_and_path" -Destination "$file_targetpath\$Timestamp3+"_"+$FileName" -PassThru -Force) Set-Variable -Name FileFinal -Value (Rename-Item -Path "FileTemp" -NewName "$FileName$VersionSeperator$FileVersion.$FileExtension") Func-Write-Logfile -LogEintrag "Command: $move_or_copy has been completed for file: $filename_and_path" Func-Write-Logfile -LogEintrag "File is ranamed to: $FileName$VersionSeperator$FileVersion.$FileExtension" Func-Write-Logfile -LogEintrag "and is transferd to: $file_targetpath" Return "$FileFinal.Fullname" } Catch { Func-Write-Logfile -LogEintrag "Error at $move_or_copy command, processing file: $filename_and_path" Func-Write-Logfile -LogEintrag "Please check your privileges" exit } IF ($move_or_copy -eq 'move') { Func-Write-Logfile -LogEintrag "Moving action was choosen, will delete original file." Try { Remove-Item -Path "$filename_and_path" -Force } Catch { Func-Write-Logfile -LogEintrag "Error removing the original file." } } ELSEIF ($MoveorCopy -eq 'copy') { Func-Write-Logfile -LogEintrag "Coping action was choosen, will not delete original file." } } ELSE { Set-Variable -Name FileTemp -Value (Copy-Item -Path "$filename_and_path" -Destination "$file_targetpath\$Timestamp3+"_"+$FileName" -PassThru -Force) Set-Variable -Name FileFinal -Value (Rename-Item -Path "FileTemp" -NewName "$FileName$VersionSeperator$FileVersion.$FileExtension") Func-Write-Logfile -LogEintrag "Command: $move_or_copy has been completed for file: $filename_and_path" Func-Write-Logfile -LogEintrag "File is ranamed to: $FileName.$FileExtension" Func-Write-Logfile -LogEintrag "and is transferd to: $file_targetpath" Return "$FileFinal.Fullname" } } #----------------------------------------------------------------------------------------------------- ####################################### Vorbereitende Arbeiten. ###################################### #----------------------------------------------------------------------------------------------------- # Lösche evtl. anzeigen. Clear-Host # Konfigurationsdatei komplett einlesen. Func-ReadConfigFile -ConfigFile $ConfigFile # Werte aus Konfigurationsdatei bereitstellen. $LogPathListe = (Func-ReadConfigValue -KonfigBezeichner LogPath) $LogKeepTime = (Func-ReadConfigValue -KonfigBezeichner LogKeepTime) $FileDelayAge = (Func-ReadConfigValue -KonfigBezeichner FileDelayAge) $VersionSeperator = (Func-ReadConfigValue -KonfigBezeichner VersionSeperator) $Sourcepath = (Func-ReadConfigValue -KonfigBezeichner Sourcepath) $Destinationpath = (Func-ReadConfigValue -KonfigBezeichner Destinationpath) $FileWhiteList = (Func-ReadConfigValue -KonfigBezeichner FileWhiteList) #----------------------------------------------------------------------------------------------------- ####################################### Hauptprogramm starten. ####################################### #----------------------------------------------------------------------------------------------------- Write-Host "" Func-Write-Logfile -LogEintrag "*******************************************************************************************" Func-Write-Logfile -LogEintrag "Program Startup: $ScriptName on $env:computername from Account $env:USERDOMAIN\$env:USERNAME." Func-Write-Logfile -LogEintrag "*******************************************************************************************" Func-Path-Check -Path $Sourcepath Func-Path-Check -Path $Destinationpath $Items = (Func-Dateien-zusammensuchen -SuchPath "$Sourcepath\*" -SuchWhiteList $FileWhiteList | where-object {$_.lastwritetime -lt (get-date).addminutes(-$FileDelayAge)} ) FOREACH ($Item in $Items) { Func-File-copy-or-move -filename_and_path "$Item" -file_targetpath $Destionationpath -move_or_copy move } #----------------------------------------------------------------------------------------------------- ####################################### Abschließende Arbeiten. ###################################### #----------------------------------------------------------------------------------------------------- # Löschen alter Log-Dateien. Func-Write-Logfile -LogEintrag "" Func-Write-Logfile -LogEintrag "-------------------------------------------------------------------------------------------" Func-Write-Logfile -LogEintrag "Prüfe ob zu löschende Log-Dateien vorhanden sind." Func-Write-Logfile -LogEintrag "-------------------------------------------------------------------------------------------" IF ($LogKeepTime -gt 0) { Func-Write-Logfile -LogEintrag "Log Files should be removed which are older than $LogKeepTime Day(s)." $Items = (Func-Dateien-zusammensuchen -SuchPath "$LogPath\*" -SuchWhiteList *.log | where {$_.Name -like "*$ScriptName*" -and $_.lastwritetime -lt $((Get-Date).AddDays(-$LogKeepTime)) -and -not $_.psiscontainer}) IF ($Items -eq $null) { Func-Write-Logfile -LogEintrag "Keine zu löschenden Log-Dateien vorhanden." } ELSE { Func-Write-Logfile -LogEintrag "Dateien gefunden, folgende Log-Dateien werden aufgund ihres alters gelöscht:" FOREACH ($Item in $Items) { Func-Write-Logfile -LogEintrag "Log-Datei: $Item wird entfernt." Remove-Item -Path $Item -Force -Verbose } } } ELSE { Func-Write-Logfile -LogEintrag "Sie haben in der Konfigurationsdatei angegeben, das Log Dateien nicht automatisch gelöscht werden sollen!" } Func-Write-Logfile -LogEintrag "" Func-Write-Logfile -LogEintrag "*******************************************************************************************" Func-Write-Logfile -LogEintrag "Program Finish: $ScriptName on $env:computername from Account $env:USERDOMAIN\$env:USERNAME." Func-Write-Logfile -LogEintrag "*******************************************************************************************" # Definierte Variablen wieder löschen, damit sie nicht im Arbeitsspeicher verbleiben. Remove-Variable -Name Skript* -Force Remove-Variable -name Konfig* -Force Remove-Variable -name ZeitStempel* -Force Remove-Variable -name Log* -Force Remove-Variable -name FileDelayAge -Force Remove-Variable -Name Path* -Force Remove-Variable -Name *Datei* -Force Remove-Variable -Name *Test* -Force Remove-Variable -Name Item -Force Remove-Variable -Name Items -Force $error.clear()