2

I am trying to move thousands of files into YYYY-MM folders, using a scheduled task which runs every night. The files are currently stored here:

C:\Users\USER\Desktop\New folder

I want them to be stored like this:

C:\Users\USER\Desktop\New folder\YYYY\MM\

eg:

C:\Users\USER\Desktop\New folder\2019\05

The script would create the YYYY\MM folders if they dont already exist. The file name is in the following format:

Status_20200116_001058.txt

So for the above file, YYYY is 2020 and the MM is 01

I found a PS script on Stack and amended it to the below, but I have not used PS much before and am a bit lost:

$Files_Folder = "C:\Users\USER\Desktop\New folder"
get-childitem | % {
    $file = $_.FullName
    $month = $date.month
    $year = $date.year

    new-item -type Directory -path "$Files_Folder\$year\$month"
    move-item $file "$Files_Folder\$year\$month"
}

Running the above results in PS creating a whole bunch of folders and files in the location above, which I cannot delete:

enter image description here

Any help would be most appreciated

Edit: So I tried the script from @Wasif Hasan like this:

$Files_Folder = "C:\Users\USER\Desktop\New folder1"
get-childitem | % {
    $file = $_.FullName
    $month = $file.substring(12, 2)
    $year = $file.substring(8, 4)
    $folder = Join-Path -Path "$($Files_Folder)" -ChildPath "$($Year)"
    $folder = Join-Path -Path "$($folder)" -ChildPath "$($Month)"
    $Exists = Test-Path "$($Folder)"
    If (!$Exists) { New-Item -Type directory -Path "$($Folder)" }
   Move-Item "$($File)" "$($Folder)"
}

However I just get a bunch of errors in PS:

enter image description here

Edit: Just tried the script by @Pavithran G, amended for using a Year and Month variable instead of Month and Date:

$loc = "C:\Users\nazadmin\Desktop\New folder1"
$files = Get-ChildItem -Path $loc
for ($i=0; $i -lt $files.Count; $i++) 
{
$outfile = $files[$i].FullName
$filename = Split-Path -Path $outfile -Leaf -Resolve
$Year = $filename -replace "Status_\d{0}(\d{4})[\d_]*.txt",'$1'
$Month = $filename -replace "Status_\d{4}(\d{2})[\d_]*.txt",'$1'
$folder = Join-Path -Path  $loc -ChildPath $Year
$folder = Join-Path -Path $folder -ChildPath $Month
$Exists = Test-Path $folder
If (!$Exists) 
{ 
    New-Item -Type directory -Path $folder 
}
Move-Item $outfile $folder
}

This works perfectly!

Edit: Just realised that if the YY folder exists already, then the script tries to create another YY folder within the YY folder, and throws an error:

Move-Item : Access to the path 'C:\Users\USER\Desktop\New folder1\2018' is denied.
At line:14 char:10
+ Move-Item <<<<  $outfile $folder
+ CategoryInfo          : WriteError: (C:\Users\USER...ew folder1\2018:DirectoryInfo) [Move-Item], IOException
+ FullyQualifiedErrorId : MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand

Any way I can avoid this situation?

Edit: Will post a new question to make it clearer Cheers

2
  • FYI you can't create folder in windows with filename that contains like any of the following characters:` \ / : * ? " < > |`.So you can't able create folder name like 2019\05..You want in any other format ? Commented Jan 17, 2020 at 10:52
  • Thats the folder path, not the folder name. So the path goes to folder 2019, then folder 05 - based on year and month in filename Commented Jan 17, 2020 at 13:05

2 Answers 2

1

Below script will create folder based on the filename present in that.So,no need to add for scheduled task, you can run at any time , it will automatically create folder,but don't change the format of the filename which you mentioned earlier.

$loc = "C:\Users\USER\Desktop\New folder"
$files = Get-ChildItem -Path $loc
for ($i=0; $i -lt $files.Count; $i++) 
{
$outfile = $files[$i].FullName
$filename = Split-Path -Path $outfile -Leaf -Resolve
$Month = $filename -replace "Status_\d{4}(\d{2})[\d_]*.txt",'$1'
$date = $filename -replace "Status_\d{6}(\d{2})[\d_]*.txt",'$1'
$folder = Join-Path -Path  $loc -ChildPath $Month
$folder = Join-Path -Path $folder -ChildPath $date
$Exists = Test-Path $folder
If (!$Exists) 
{ 
    New-Item -Type directory -Path $folder 
}
Move-Item $outfile $folder
}

Make sure ,run the Powershell script in Admin mode because sometimes it need administrator access to move or copy file

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

1 Comment

Thanks for this @pavithran G, I have amended this slightly to add a $Year variable, as I am storing files in $Year then $Month folders, I have added that into the main post
0

$date is not declared as a date variable (Get-Date). Use Join-Path to safely create paths and you have not used Test-Path check the folder existence. Use this:

$date = Get-Date
$Files_Folder = "C:\Users\USER\Desktop\New folder"
get-childitem | % {
    $file = $_.FullName
    $month = $date.month
    $year = $date.year
    $folder = Join-Path -Path "$($Files_Folder)" -ChildPath "$($Year)"
    $folder = Join-Path -Path "$($folder)" -ChildPath "$($Month)"
    $Exists = Test-Path "$($Folder)"
    If (!$Exists) { New-Item -Type directory -Path "$($Folder)" }
   Move-Item "$($File)" "$($Folder)"
}

5 Comments

He asking a folder name like '2019\05' as same folder ,not folder within folder
Hi @pavithranG thats the folder path, not the folder name. I will test this and reply back asap
Hi @Wasif Hasan the $month and $year variables need to be based on the filename, not the system date - is this possible please? So $year is based on the 8th to 11th characters in filename, $month is based on the 12th to 13th characters in filename
Actually just figured it out, to use substring function. I will test this and reply back
I get errors when using this, please see main post

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.