Jos Jonkeren
Jos Jonkeren

Reputation: 93

Powershell command / script to move files to subdirectories based on date (in the first 8 characters of the file name)

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.

Upvotes: 1

Views: 256

Answers (2)

Abraham Zinala
Abraham Zinala

Reputation: 4694

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

Upvotes: 0

Vivere
Vivere

Reputation: 2270

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.

Upvotes: 3

Related Questions