xyxy-yx
Goto Top

Datein nach Erstellungsdatum in Unterornder verschieben

Hallo,

ich möchte alle Dateien nach Erstellungsdatum in datumbenannte Unterordner kopieren und eventuell diesen auch erstellen, wenn er nicht vorhanden ist.
Beispiel:
aaaaaa.jpg Erstellt am 01.04.2016 soll in den Unterordner 2016.04 verschoben werden
bbbbbb.jpg Erstellt am 01.05.2016 soll in den Unterordner 2016.05 verschoben werden

am besten in Powershell.

schon mal danke im Voraus

Content-ID: 303915

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

Ausgedruckt am: 26.11.2024 um 04:11 Uhr

H41mSh1C0R
H41mSh1C0R 07.05.2016 um 21:40:24 Uhr
Goto Top
Schon irgendwelche Scriptversuche vorhanden? Wenn ja wo klemmts?
129148
129148 07.05.2016, aktualisiert am 08.05.2016 um 08:48:57 Uhr
Goto Top
$ordner = 'c:\deinordner'  
dir $ordner -File | group {$_.CreationTime.toString("yyyy.MM")} | %{  
    $ziel = "$ordner\$($_.Name)"  
    if (!(test-path $ziel)){md $ziel -Force}
    move-item $_.Group $ziel -Force
}
xyxy-yx
xyxy-yx 08.05.2016 um 12:00:50 Uhr
Goto Top
Hallo 1122tra,
danke für den Code, aber leider funktioniert er bei mir noch nicht ganz:
Mein Ordner ist
$ordner = 'c:\Test\sort'  
aber leider schreibt move-item einen Fehler
move-item : Cannot find path 'C:\Users\Asus\aaaaaa.JPG' because it does not exist.  
At C:\Test\DatumSort.ps1:5 char:5
+     move-item $_.Group $ziel -Force
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (C:\Users\Asus\aaaaaa.JPG:String) [Move- 
   Item], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
 
Und das Skript leget nur einen Ordner mit dem heutigen Datum an (2016.05).
Ich habe auch
$_.Group | move-item -Destination $ziel-EA Ignore
versucht, aber da wird die Dateien in den Ordner 2016.05 verschoben und nicht in den Ordner 2015.12 (Erstellungsdatum von aaaaaa.jpg).
Wäre es auch möglich noch
function Get-ScriptDirectory {
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}
$pfad=  Get-ScriptDirectory 
$ordner = "$pfad\sort"  
hineinzubringen da die Skriptdatei auf
c:\Test 
liegt und die Ordner "2016.05", ... im Skript-Ordner zu erstellen.

besten Danke schon mal im Voraus
129148
129148 08.05.2016 aktualisiert um 12:15:52 Uhr
Goto Top
Geht hier fehlerfrei. Wahrscheinlich mal wieder alte Powershell benutzt.
Aktuellen Pfad bekommst du so
Split-Path -Parent -Path $MyInvocation.MyCommand.Definition

$ordner = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
dir $ordner -File | group {$_.CreationTime.toString("yyyy.MM")} | %{  
    $ziel = "$ordner\$($_.Name)"  
    if (!(test-path $ziel)){md $ziel -Force}
    move-item $_.Group  -Destination $ziel -Force
}
macht hier genau das was du willst, fehlerfrei. Fehler muss also bei dir liegen.
xyxy-yx
xyxy-yx 08.05.2016 um 12:18:40 Uhr
Goto Top
Hallo H41mSh1C0R,
ich habe leider noch keine Skriptversuche gestartet.
Bin gerade dabei mir Powershell anzueignen um die kleinen, öfters langwierigen PC-Problemchen zu lösen.
xyxy-yx
xyxy-yx 08.05.2016 um 16:06:34 Uhr
Goto Top
Hallo 1122tra,
habe Powershell 5, weil ich schon mal Probleme hatte. Dein Skript funktioniert auch bei mir tadellos, nachdem ich Powershell als admin gestartet hatte, war mein Fehler. Weil alle Datein in den 2016.05 Ordner verschoben waren, lag bei meinen Testfiles. Ich habe sie in einen Test-Ordner kopiert und dadurch war das Erstellungsdatum von Heute. Leider bin ich erst jetzt draufgekommen, dass wenn ich Fotos sortieren möchte ich aber das Aufnahmedatum und nicht das Erstellungsdatum brauche; war wieder mein Fehler.
Ist es sehr aufwendig das Skript so umzuändern, dass nicht nach Erstellungs- sondern nach Aufnahmedatum sortierten wird.

Danke im Voraus.
129148
129148 08.05.2016 aktualisiert um 17:53:01 Uhr
Goto Top
Dafür musst du die erweiterten Dateieigenschaften abfragen, oder mit einem EXIF-Tool das Datum auslesen
Das hier könntest du einfach mit in die Pipe einbauen:
Erweiterte Dateieigenschaften mit Powershell-Funktion abfragen
xyxy-yx
xyxy-yx 08.05.2016 um 20:16:45 Uhr
Goto Top
Hier mal mein Code:

function Get-ScriptDirectory {
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}
function Add-ExtendedFileProperties{
 <#
     .SYNOPSIS
        Fügt erweiterte Eigenschaften von Dateien an das Objekt in der Pipline hinzu
     .DESCRIPTION
        Extrahiert erweiterte Eigenschaften von Dateien wie z.B. Exif-Daten, Musik- bzw. Filmdetails
     .EXAMPLE 
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties -PropertyExtended "Bildhöhe","Bildbreite","Datenrate" | ft Name,Bildhöhe,Bildbreite,Datenrate  
            Fügt alle nur die Eigenschaften "Bildhöhe","Bildbreite","Datenrate" als zusätzliche Spalten dem Objekt in der Pipline hinzu  
     .EXAMPLE
            Get-ChildItem "C:\Temp" | Add-ExtendedFileProperties | fl *  
            Fügt alle verfügbaren erweiterten Eigenschaften dem Objekt in der Pipline hinzu
     .PARAMETER PropertyExtended
        Mit diesem Parameter geben sie eine Komma-Separierte Liste von Eigenschaften an welche sie erhalten möchten.
            -PropertyExtended "Bildhöhe","Bildbreite","Bitrate"  
#>
    param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
        $fileItem,
        [String[]] $PropertyExtended = "ALL"  
    )
    begin
    {
        $shellObject = New-Object -Com Shell.Application
        $itemProperties = $null
    }
    process
    {
        if($fileItem.PsIsContainer)
        {
            $fileItem
            return
        }
        $directoryName = $fileItem.DirectoryName
        $filename = $fileItem.Name

        $folderObject = $shellObject.NameSpace($directoryName)
        $item = $folderObject.ParseName($filename)

        if(-not $itemProperties)
        {
            $itemProperties = @{}
            $counter = 0
            $columnName = ""  
            if ($PropertyExtended -eq "ALL"){  
                 #get all properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    if($columnName) { $itemProperties[$counter] = $columnName }
                    $counter++
                }while($columnName)
            }else{
                #get user defined properties
                do {
                    $columnName = $folderObject.GetDetailsOf($folderObject.Items, $counter)
                    foreach($name in $PropertyExtended){
                        if ($columnName.toLower() -eq $name.toLower()){
                            $itemProperties[$counter] = $columnName
                        }
                    }
                    $counter++
                }while($columnName)
            }
        }

        foreach($itemProperty in $itemProperties.Keys)
        {
            $fileItem | Add-Member NoteProperty $itemProperties[$itemProperty] `
                $folderObject.GetDetailsOf($item, $itemProperty) -ErrorAction `
                SilentlyContinue
        }
        $fileItem
    }
}
$ordner = Get-ScriptDirectory
$fileordner = "$ordner\sort"  
dir $fileordner -File |  Add-ExtendedFileProperties -PropertyExtended "Aufnahmedatum" | group {$_????.toString("yyyy.MM")} | %{  
    $ziel = "$ordner\$($_.Name)"  
    if (!(test-path $ziel)){md $ziel -Force}
    move-item $_.Group  -Destination $ziel -EA Ignore
    }

Leider habe keine Ahnung ich das Aufnahmedatum in das Formt yyyy.MM umwandeln kann. Und move-item soll die Datei, falls sie schon vorhanden ist nicht kopieren, drum -EA Ignore.
129148
129148 08.05.2016 um 20:20:33 Uhr
Goto Top
Mit get-Date das String-Datum in ein richtiges Datum umwandeln und mit Parameter -F formatiert ausgeben.
xyxy-yx
xyxy-yx 08.05.2016 um 20:49:04 Uhr
Goto Top
besten Dank mit
... Add-ExtendedFileProperties -PropertyExtended "Aufnahmedatum" | group {Get-Date -format yyyy.MM} ...  
funktioniert alles wunderbar
xyxy-yx
xyxy-yx 08.05.2016 um 21:03:44 Uhr
Goto Top
Irgendwie wird nur das heutige Datum genommen nicht das Aufnahmedatum, funktioniert doch noch nicht so ganz
129148
129148 08.05.2016 aktualisiert um 21:07:12 Uhr
Goto Top
Zitat von @xyxy-yx:

Irgendwie wird nur das heutige Datum genommen nicht das Aufnahmedatum, funktioniert doch noch nicht so ganz
Ist ja auch logisch denn du hast vergessen die Eigenschaft Aufnahmedatum bei get-Date anzugeben, ohne diese Angabe nimmt er das heutige Datum face-wink !
group {Get-Date $_.Aufnahmedatum -format yyyy.MM}
xyxy-yx
xyxy-yx 08.05.2016 um 21:07:09 Uhr
Goto Top
wie macht man das?
xyxy-yx
xyxy-yx 08.05.2016 um 21:07:58 Uhr
Goto Top
danke schön, habe zu schnell geschrieben
129148
129148 08.05.2016 um 21:08:00 Uhr
Goto Top
s.o.
und ab und zu mal ins Manual sehen, da steht es ebenfalls.
xyxy-yx
xyxy-yx 08.05.2016 um 21:15:06 Uhr
Goto Top
Jetzt kommt leider eine Fehlermeldung:
group : Cannot bind parameter 'Date'. Cannot convert value "‎18.‎05.‎2015 ‏‎09:11" to type   
"System.DateTime". Error: "Die Zeichenfolge wurde nicht als gültiges DateTime erkannt."  
At C:\Test\DatumSortieren.ps1:81 char:87
+ ... fnahmedatum" | group {Get-Date $_.Aufnahmedatum -format yyyy.MM} | %{  
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidResult: (20150518_091117.jpg:PSObject) [Group-Object], ParameterB 
   indingException
    + FullyQualifiedErrorId : ExpressionEvaluation,Microsoft.PowerShell.Commands.GroupObjectCommand
 
129148
Lösung 129148 08.05.2016 aktualisiert um 21:26:59 Uhr
Goto Top
Dann ergänze den String vorher noch um die Sekunden :00 bevor du ihn an get-Date verfütterst oder nutze stattdessen DateTime::TryParse

Natürlich solltest du vorher auch prüfen ob im Aufnahmedatum überhaupt etwas steht und ob es als Datum interpretiert werden kann: Stichwort where-object
xyxy-yx
xyxy-yx 08.05.2016 um 21:37:12 Uhr
Goto Top
wie würde es mit DateTime::TryParse funktionieren?
129148
Lösung 129148 08.05.2016 aktualisiert um 21:43:43 Uhr
Goto Top
Zitat von @xyxy-yx:

wie würde es mit DateTime::TryParse funktionieren?
Oh man, echt Kindergarten hier:
Erst mit TryParse alle Bilder ausfiltern die ein gültiges Aufnahmedatum haben und dann mit [DateTime]::Parse zum Datum umwandeln
Steht alles da, man muss es nur lesen
https://msdn.microsoft.com/de-de/library/system.datetime.tryparse(v=vs.1 ...
https://msdn.microsoft.com/de-de/library/system.datetime.parse(v=vs.110) ...
xyxy-yx
xyxy-yx 11.05.2016 um 20:43:59 Uhr
Goto Top
Habe noch ein wenig herumgespielt. Hier nochmal der Code, falls ihn wer benötigt:
function Get-ScriptDirectory siehe oben
function Add-ExtendedFileProperties siehe oben

$ordner = Get-ScriptDirectory
$fileordner = "$ordner\sort"  
$Dateien = dir $fileordner -File | Add-ExtendedFileProperties -PropertyExtended "Aufnahmedatum"   
 foreach ( $Datei in $Dateien){
  $datum=$Datei.Aufnahmedatum -replace '([^0-9.: ])',''  
 
  try{
    $Verz=[DateTime]::ParseExact($datum,'dd.MM.yyyy HH:mm', [System.Globalization.CultureInfo]::InvariantCulture).ToString("yyyy.MM")  
    if (!(test-path "$ordner\$Verz")){md "$ordner\$Verz" -Force}   
    move-item $Datei.FullName -Destination "$ordner\$Verz" -EA Ignore  
    }
   catch{}
}