Create a folder from a file name which has 2 underscores, then place that file in the folder

Viewed 194

I try to create a folder using PowerShell for the following files

4_2017-07-16_01-22-52.mp4
4_2017-07-16_01-23-50.mp4
4_2017-07-16_01-24-54.mp4
4_2017-07-16_01-26-21.mp4

I use this method

https://stackoverflow.com/a/41468253/13002495

the problem that it will create a directory 4 then move the files to it what I need to have a directory like the following

4_2017-07-16 or a directory like 4_2017_07_16

this is the first method.

the second method if you can help to have a script to create the following directories

2017 directory then a subdirectory 02 then subdirectory 16 then a subdirectory 4 then move the files to subdirectory 4

so it will be as following

2017
--------07
------------16
---------------------04 ----> files will be here 

can you help with these 2 methods?

2 Answers

You could try something like this:

$folder = 'FILES_FOLDER'

Get-ChildItem -Path $folder | ForEach-Object {
    $subFolders = $_.Name.Split("-_")
    $path = Get-Location
    $order = 1, 2, 3, 0

    $order | ForEach-Object {
        $path = Join-Path -Path $path -ChildPath $subFolders[$_]

        if (-not (Test-Path -Path $path -PathType Container)){
            New-Item -Path $path -ItemType Directory
        }
    }

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

Which will move all files to:

2017/07/16/4/4_2017-07-16_01-22-52.mp4
2017/07/16/4/4_2017-07-16_01-23-50.mp4
2017/07/16/4/4_2017-07-16_01-24-54.mp4
2017/07/16/4/4_2017-07-16_01-26-21.mp4

Explanation:

  • Split the files on "-" and "_" with Split. Can look at about_split for more information.
  • Get the current folder path with Get-Location, which is used to append to the current path for making sub directories.
  • Create an $order array to create the correct sub folder order as shown in the question.
  • Iterate through this $order array and create new directories if they dont exist. Can use Test-Path to check if the sub folders exist, and New-Item to create a new directory.
  • Move files to final sub directory with Move-Item. These sub directories will be in your current working directory. You could obviously change this to another directory location as well.

For your first method (one destination folder with name like 4_2017_07_16), you can do:

$source      = 'D:\Mp4Files'  # rootfolder where the files are
$destination = 'D:\Test'      # rootfolder where the files need to go
Get-ChildItem -Path $source -File -Filter '*.mp4' |
  Group-Object { ($_.BaseName -replace'(\d+_[^_]+).*', '$1') } |
  ForEach-Object {
    $targetFolder = Join-Path -Path $destination -ChildPath $_.Name
    # create this folder if it does not already exist
    if (!(Test-Path -Path $targetFolder -PathType Container)) {
        $null = New-Item -Path $targetFolder -ItemType Directory
    }
    $_.Group | Move-Item -Destination $targetFolder
}

Result:

D:\TEST\4_2017-07-16
    4_2017-07-16_01-22-52.mp4
    4_2017-07-16_01-23-50.mp4
    4_2017-07-16_01-24-54.mp4
    4_2017-07-16_01-26-21.mp4

The second method creates more subfolders, based on the first part of the filenames:

$source      = 'D:\Mp4Files'
$destination = 'D:\Test'
Get-ChildItem -Path $source -File -Filter '*.mp4' |
  Group-Object { ($_.BaseName -replace'(\d+_[^_]+).*', '$1') } |
  ForEach-Object {
    $index, $year, $month, $day = $_.Name -split '[-_]'
    $targetFolder = Join-Path -Path $destination -ChildPath ('{0}\{1:00}\{2:00}\{3:00}' -f $year, [int]$month, [int]$day, [int]$index)
    # create this folder if it does not already exist
    if (!(Test-Path -Path $targetFolder -PathType Container)) {
        $null = New-Item -Path $targetFolder -ItemType Directory
    }
    $_.Group | Move-Item -Destination $targetFolder
}

Result:

D:\TEST\2017
\---07
    \---16
        \---04
                4_2017-07-16_01-22-52.mp4
                4_2017-07-16_01-23-50.mp4
                4_2017-07-16_01-24-54.mp4
                4_2017-07-16_01-26-21.mp4
Related