Naz
Naz

Reputation: 525

Use a scheduled task to move files into specific YY-MM folders based on file name

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

Upvotes: 2

Views: 1316

Answers (2)

pavithran G
pavithran G

Reputation: 112

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

Upvotes: 1

wasif
wasif

Reputation: 15478

$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)"
}

Upvotes: 0

Related Questions