1

I have a bunch of files like these in a directory, many thousands of them.

20210528_195406.jpg
20210528_195406.xmp
20210529_113416.mp4
20210529_113416.xmp
20210529_151444.jpg
20210529_151444.xmp
20210530_150950.mp4
20210530_150950.xmp
20210601_175932.txt
20210601_175932~2.mp4
20210601_175932~2.xmp

I am looking for an easy way (Powershell command) to copy the files to subdirectories based on year / month / day.

So for example, the file 20210601_175932.jpg would be moved to (a newly created) subdirectory: 2021\06\01\.

How do I do this with Powershell? I know that Exiftool can do this by using: exiftool -v -ext jpg -ext mp4 "-Directory<CreateDate" -d %Y\%m\%d\ .

But this only works for image and video files.

Any idea how to solve this for all file types?

Thanks.

1
  • Update: I found a way to extract parts of the file name. ``` Get-ChildItem .\ | Select Name, @{N='Year';E={$_.BaseName.SubString(0,4)}}, @{N='Month';E={$_.BaseName.SubString(4,2)}}, @{N='Day';E={$_.BaseName.SubString(6,2)}} ``` Commented Jun 4, 2021 at 12:55

2 Answers 2

3

I believe something like this would suffice:

$dataPath = "$PSScriptRoot/data"
$newDataPath = "$PSScriptRoot/structuredData"
Get-ChildItem $dataPath | ForEach-Object {
    $year = $_.BaseName.Substring(0, 4)
    $month = $_.BaseName.Substring(4, 2)
    $day = $_.BaseName.Substring(6, 2)

    $path = "$newDataPath\$year\$month\$day"
    if (-not (Test-Path $path)) {
        New-Item -ItemType Directory -Path $path
    }

    Move-Item -Path $_.FullName -Destination $path
}

I'm iterating all the files found in the directory, get the year, month and day from the file name then I check if the path exists. If it doesn't I create it. Then I move the file there.

Sign up to request clarification or add additional context in comments.

2 Comments

Lol had the same thought process. Beat me to it tho(:
Thank you!! This does exactly what I need :)
0

So, something like this?

$Folder_Location = "C:\brief\datefolder"

Get-ChildItem -Path $Folder_Location -File | 
    ForEach-Object -Process {
        
        #Assign current object in pipeline to something more readable
        $File = $_
        #$Folder_Name = [datetime]::ParseExact("$($File.Name.Split('_')[0])", "yyyymmdd", $null)
        #Split the name at the underscore keeping just the "date"
        $Folder_Name = $File.Name.Split('_')[0]
        
        #Assign the full destination path to a variable and test against it
        $Destination_Path = "C:\brief\datefolder\$Folder_Name"
        $Test_Destination = Test-Path -Path $Destination_Path
        
        #Evaluate against the returned bool value from $Test_Destination
        if ($Test_Destination -eq $False){

            #if folder doesn't exist, create it, and move the file in it
            New-Item -Path C:\brief\datefolder -Name $Folder_Name -ItemType Directory
            Move-Item -Path $File.FullName -Destination $Destination_Path

        }
        else { 

            #"Folder exists"
            #If folder already exists, just move the file.
            Move-Item -Path $File.FullName -Destination $Destination_Path

        }
    }

Given that you want to move them all into directories within the same one that you're pulling from.

Edit: added some inline comments

2 Comments

Wow, thanks! I tried that out, and it does work. However, it creates subdirectories based on the date (one string). So \20210523\ etc. Is there any way to make it create the sub-subdiectories, so \2021\05\23\ ?
I have now also seen the answer by Vivere, and that does what I wanted to achieve. Thank you all very much for helping out!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.