Powershell: Move files to folder based on Date Created - powershell

I'm not a coder but I've still attempted tweaking PS scripts found here and still can't get the behavior I desire. The tough part for me has been the 2 digit Day requirement (dd). After several noob attempts I would like some help.
I have a folder that contains hundreds of JPG's. I manually sort these JPG's into folders based on the date taken. Folder name examples are 2015.02.04, 2016.10.31, 2016.12.01.
1) I would like a script to scan my JPG folder.
2) For each file, scan the date
3) If the file was created June 1st, 2016 then it will be moved to .\2016.06.01
Help a brother out?
$Filepath = ""
$file = ""
$date = ""
$month = ""
$year = ""
$MonthPath = ""
$FilePath = Read-Host "Place the directory which contains the files."
Write-Warning "Note: This action can take several minutes, depending on the amount of files in $FilePath."
get-childitem $FilePath | % {
$file = $_.FullName
$date = Get-Date ($_.LastWriteTime)
$month = $date.month
$year = $date.year
$day = $date.day
$MonthPath = "$FilePath\$year.$month.$day"
Write-Verbose "month = $month"
Write-Verbose "Date = $date"
Write-Verbose "year = $year"
Write-Verbose "FilePath = $FilePath"
Write-Verbose "Filename = $file"
Write-Verbose "MonthPath = $MonthPath"
if(!(Test-Path -Path "$MonthPath" )){
Write-Verbose "Creating log location $MonthPath."
#Write-Host -backgroundcolor green -ForegroundColor black "Creating log location $MonthPath."
Write-Verbose "MonthPath inside path test = $MonthPath"
New-Item -ItemType directory -Path $MonthPath | Out-null
}
ELSE {
#Write-Host -backgroundcolor green -ForegroundColor black "Log location exists already exist $MonthPath"
Write-Verbose "Log location exists already exist $MonthPath"
}
move-item "$file" "$MonthPath" | Out-null
}
Write-Warning "All files are sorted now based upon year and month."

[DateTime]$start_time="2016-6-1 00:00:00"
[DateTime]$end_time="2016-6-1 23:59:59"
$des_folder = "C:\test\2016.06.1"
Get-ChildItem c:\test\*.jpg -Recurse | foreach {if($_.lastwritetime -ge $start_time -and $_.lastwritetime -le $end_time) { move-item $_.fullname $des_folder }}
Please ensure there is no name conflict .
You may change"c:\test" in "c:\test*.jpg" to the path you want to scan .
Also the value of variable "$des_folder" to the destination folder you want to store the matched pictures .
EDIT:
Get-ChildItem c:\test\test2\*.jpg -Recurse | foreach {
$x = $_.LastWriteTime.ToShortDateString()
$new_folder_name = Get-Date $x -Format yyyy.MM.dd
$des_path = "c:\test\test2\$new_folder_name"
if (test-path $des_path){
move-item $_.fullname $des_path
} else {
new-item -ItemType directory -Path $des_path
move-item $_.fullname $des_path
}
}

I ended up creating a script that does exactly what you're asking for here. You can find it in GitHub here, which will have the latest version of the code.
Here is the current implementation, edited for conciseness, removed unnecessary features, and tailored to the question's needs:
[string] $SourceDirectoryPath = 'C:\FilesToMove'
[string] $TargetDirectoryPath = 'C:\SortedFiles'
[System.Collections.ArrayList] $filesToMove = Get-ChildItem -Path $SourceDirectoryPath -File -Force -Recurse
$filesToMove | ForEach-Object {
[System.IO.FileInfo] $file = $_
[DateTime] $fileDate = $file.LastWriteTime
[string] $dateDirectoryName = $fileDate.ToString('yyyy.MM.dd')
[string] $dateDirectoryPath = Join-Path -Path $TargetDirectoryPath -ChildPath $dateDirectoryName
if (!(Test-Path -Path $dateDirectoryPath -PathType Container))
{
Write-Verbose "Creating directory '$dateDirectoryPath'."
New-Item -Path $dateDirectoryPath-ItemType Directory -Force > $null
}
[string] $filePath = $file.FullName
Write-Information "Moving file '$filePath' into directory '$dateDirectoryPath'."
Move-Item -Path $filePath -Destination $dateDirectoryPath
}
Note that it copies the file paths into an array before iterating over them. This is important for the cases where you are copying files to subdirectories of their current directory, otherwise Get-ChildItem could scan files twice, iterating over files that it just moved.

Expanded more to cover off duplicates
$jpg_files = Get-ChildItem "F:\*.jpg" -Recurse
foreach ($jpg in $jpg_files){
$x = $jpg.LastWriteTime.ToShortDateString()
$new_folder = Get-Date $x -Format yyyy-MM-dd
$des_path = "F:\Photos\$($new_folder)"
if (Test-Path $des_path){
if (Test-Path "$($des_path)\$($jpg.Name)"){
$index = 1
do {
$new_name = $des_path + "\" + $jpg.BaseName + " ($($index))" + $jpg.Extension
$index++
} While(Test-Path $new_name)
move-item $jpg.fullname -destination $new_name
}else {
move-item $jpg.fullname $des_path
}
}
else {
new-item -ItemType directory -Path $des_path
move-item $jpg.fullname $des_path
}

I would like to propose this variant based on last response for duplicates showing that multiple files can be selected and also that removing the absolute paths works and it will move the files that are bellow of your current prompt no mathers where the file is. Also add a missing }. Thanks to all that contributes to this thread, this helps a lot to organize the pictures and video!
$files = Get-ChildItem "*.jpg","*.mp4" -Recurse
foreach ($file in $files) {
$x = $file.LastWriteTime.ToShortDateString()
$new_folder = Get-Date $x -Format yyyy-MM
$des_path = "$($new_folder)"
if (Test-Path $des_path) {
if (Test-Path "$($des_path)\$($file.Name)") {
$index = 1
do {
$new_name = $des_path + "\" + $file.BaseName + " ($($index))" + $file.Extension
$index++
} While(Test-Path $new_name)
move-item $file.fullname -destination $new_name
}else {
move-item $file.fullname $des_path
}
}
else {
new-item -ItemType directory -Path $des_path
move-item $file.fullname $des_path
}
}

Related

Archive files from a folder which are older than one week to a sub folder using powershell

I have tried below powershell script to move files older than 7 days from Newfolder to Archive_folder. The script is moving the entire path to the Archive_folder (means its creating folders \Users\529817\New folder in to Archive_folder and then copying files and not zipping the folder) , I need help in copying only files from NewFolder to Archive_folder and zip that folder.
$ArchiveYear = "2018"
$ArchiveMonth = "10"
$ArchiveDay = "10"
$SourcePath = "C:\Users\529817\New folder"
$TargetPath = "C:\Users\529817\New folder\Archive_folder"
$YourDirToCompress = "C:\Users\529817\New folder"
$ZipFileResult = "C:\Users\529817\New folder\Archive_folder\$ArchiveDay$ArchiveMonth.zip"
Get-ChildItem $YourDirToCompress -Directory |
#where { $_.Name -notin $DirToExclude} |
Compress-Archive -DestinationPath $ZipFileResult -Update
$Days = "7"
$LogPath = "C:Users\529817\Temp"
$Date = Get-Date -format yyyy-MM-dd_HH-mm
$TargetFolder = "$TargetPath\$Date"
$LogFile = "$LogPath\ArchiveLog-$date.txt"
$TargetZipFile = "$TargetPath\$Date.zip"
$Activity = "Move files older than $Days days from $SourcePath to $TargetFolder"
Write-Verbose $Activity
$OldFiles = Get-Childitem -Path $SourcePath -recurse | Where-Object {$_.LastWriteTime -lt (get-date).AddDays( - $days)}
$Total = $Oldfiles.Count
$Current = 0
$OldFiles | ForEach {
$Current ++
$Filename = $_.fullname
Write-Progress -Activity $Activity -Status $FileName -PercentComplete ($Current / $Total * 100)
$Split = $FileName -split '\\'
$DestFile = $split[1..($split.Length - 1)] -join '\'
$DestFile = "$TargetFolder\$DestFile"
Try {
$null = New-Item -Path $DestFile -Type File -Force
$Null = Move-Item -Path $FileName -Destination $DestFile -Force -ErrorAction:SilentlyContinue
"Successfully moved $filename to $targetfolder" | add-content $LogFile
}
Catch {
$Err = $_.Exception.Message
Write-Error $Err
"Error moving $filename`: $Err " | add-content $LogFile
}
}
You have two problems here:
Your zip file isn't going where you want it to go
Instead, all of the items which should be in the zip are going where the zip should go.
Let's figure out why this is happening so you can do what you need to get it working.
Problem 1
You have line 10 which looks like this:
Compress-Archive -DestinationPath $ZipFileResult -Update
This creates the Zip file but you don't actually do anything with this file, as in we don't see this $ZipFileResult used again in the code. This is why your zip file isn't showing up where you want it to be.
Problem 2
The end of this script has this big block where you are expressly copying the files to the directory,right where you don't want them.
Try {
$null = New-Item -Path $DestFile -Type File -Force
$Null = Move-Item -Path $FileName -Destination $DestFile -Force -ErrorAction:SilentlyContinue
"Successfully moved $filename to $targetfolder" | add-content $LogFile
}
If you only want to move the Zip file, then you can shorten this whole script. Delete everything from line 19 and on down, which begins with this line.
$OldFiles = Get-Childitem -Path $SourcePath -recurse | Where-Object {$_.LastWriteTime -lt (get-date).AddDays( - $days)}
And instead, add a Move-Item command to copy that $ZipFileResult file over to whichever directory you want it to go.
Finally, there are a number of lines which don't do anythign and can be deleted, like this line $TargetZipFile = "$TargetPath\$Date.zip"

Powershell Script copying file from yesterday to other folder

I'd like to copy test.csv from folders test1 to test2, only if the file has yesterdays timestamp on. The code I'm currently working with doesn't copy my file and returns:
Not copying ...\Desktop\test1\test.csv
$DestingationFolder = "...\Desktop\test2"
$EarliestModifiedTime = (Get-date).AddDays(-1)
$Files = Get-ChildItem "...\Desktop\test1\test.csv" -File
foreach ($File in $Files)
{
if ($File.LastWriteTime -gt $EarliestModifiedTime)
{
Copy-Item $File -Destination $DestingationFolder
Write-Host "Copying $File"
}
else
{
Write-Host "Not copying $File"
}
}
Expected: Copy test.csv only if it's timestamp is from yesterday
Actual: Nothing happens and get Not copying ...\Desktop\test1\test.csv returned
Not sure if it's worth deleting the question or not but found this worked for me. Mentioned in the comments above, ... is in my paths only to make make them shorter for the question.
$DestingationFolder = "...\Desktop\test2"
$Files = Get-ChildItem "...\Desktop\test1\test.csv" -File
foreach ($File in $Files)
{
if ($File.LastWriteTime -gt (get-date).AddDays(-1).ToString("MM/dd/yyyy HH:mm:ss"))
{
Copy-Item $File -Destination $DestingationFolder
Write-Host "Copying $File"
}
else
{
Write-Host "Not copying $File"
}
}
Windows 10 64-bit. PowerShell 5
You misspelled DestinationFolder and forgot to create the folder %userprofile%\Desktop\test2
$DestinationFolder = "%userprofile%\Desktop\test2"
If(!(test-path $DestinationFolder))
{
New-Item -ItemType Directory -Force -Path $DestinationFolder
}
$EarliestModifiedTime = (Get-date).AddDays(-1)
$Files = Get-ChildItem "%userprofile%\Desktop\test1\test.csv" -File
foreach ($File in $Files)
{
if ($File.LastWriteTime -gt $EarliestModifiedTime)
{
Copy-Item $File -Destination $DestinationFolder
Write-Host "Copying $File"
}
else
{
Write-Host "Not copying $File"
}
}

Move files to sub folders based upon year and month LastWriteTime persevering subfolder

Could you help me with a modification to this script?
I have a root folder with several sub folders
c://root/ many-subfolders/ many-logfiles.
I would like the sctipt to sort long files year /month and output to the original subfolder excluding files from current year
c://root/many-subfolders/year/month/logfiles
$Filepath = ""
$file = ""
$date = ""
$month = ""
$year = ""
$MonthPath = ""
$FilePath = Read-Host "Place the directory which contains the files."
Write-Warning "Note: This action can take several minutes, depending on the amount of files in $FilePath."
Get-ChildItem $FilePath | % {
$file = $_.FullName
$date = Get-Date ($_.LastWriteTime)
$month = $date.Month
$year = $date.Year
$MonthPath = "$FilePath\$year\$month"
Write-Verbose "month = $month"
Write-Verbose "Date = $date"
Write-Verbose "year = $year"
Write-Verbose "FilePath = $FilePath"
Write-Verbose "Filename = $file"
Write-Verbose "MonthPath = $MonthPath"
if (!(Test-Path -Path "$MonthPath" )) {
Write-Verbose "Creating log location $MonthPath."
#Write-Host -BackgroundColor green -ForegroundColor black "Creating log location $MonthPath."
Write-Verbose "MonthPath inside path test = $MonthPath"
New-Item -ItemType Directory -Path $MonthPath | Out-Null
} else {
#Write-Host -BackgroundColor green -ForegroundColor black "Log location exists already exist $MonthPath"
Write-Verbose "Log location exists already exist $MonthPath"
}
Move-Item "$file" "$MonthPath" | Out-Null
}
Write-Warning "All files are sorted now based upon year and month."
as I can understand you need to filter all your files in the c:\root\ and then move them to a new directory.
# Set the $Filepath you are going to search for the files, if you have a specific extension you may filter that for better results and performance.
$FilePath = "C:\setup\testlogs"
# Put all the files to an variable with some of their attributes you may need the CreationTime or the LastWriteTime depends on what you need!!!!
$AllFiles = Get-ChildItem -Path C:\Setup\TestLogs -File -Recurse |select Name, FullName, CreationTime, LastWriteTime
Foreach ($File in $AllFiles)
{
# Put an if with less than the date you want the logs to be moved.
If ($File.LastWriteTime -lt "11/07/2018")
{
Write-Host "The file is ready for archive"
$Date = Get-Date ($File.LastWriteTime) -Format dd/MM/yyyy
$Month = $File.LastWriteTime.Month
$Year = $File.LastWriteTime.Year
$NewPath = "$FilePath\$year\$month"
$CheckExist = Test-Path $FilePath\$year\$month
# Check if the path already exist and move the file to the folder Else create the new folder and move the file there
If ($CheckExist -eq $true)
{
Move-Item -Path $File.FullName -Destination $FilePath\$year\$month\
}
Else
{
New-Item -Path $Filepath\$year\$month -ItemType Directory
Move-Item -Path $File.FullName -Destination $FilePath\$year\$month\
}
}
Else
{
Write-Host "The File is not that old to be archived"
}
}
I hope this is what you are looking for!
Let me know so I can help you more with your problem.

PowerShell Move-Item to folders efficiently

I am trying to to create an efficient PowerShell script that moves a list of files of .xlsx extension into another folder. About 30 files get generated with the current month and year at the end e.g "- January 2018" into this folder path \otnas6uk\sd.test-it.com$\PROJECTS\
Ideally if the Month and Year could be defined at the start so it loops through all files in the root directory and moves them to the correct folder listed.
This is pseudocode of how I think it could work.
$month = "February"
$year = "2018"
Move-Item -Path "\\otnas6uk\sd.test-it.com$\PROJECTS\\Zentic Report - $month $year.xlsx" -Destination \\zemnas\sd.Zentic-test.com$\Technology\Reports
All files and destinations would be predefined with only the month and year used as a parameter.
#region inputs
$month = 12
$year = 2018
$sourceDirectory = "C:\temp"
$destinationDirectory = "C:\destination"
$fileFilter = "*.xlsx"
#endregion
#region input validation
if (-not (Test-Path -Path $sourceDirectory)) {
throw "Can't find source directory"
}
# Month has to be between 1 and 12
if ($month -lt 1 -or
$month -gt 12
) {
throw "BAD MONTH!"
}
# Recent-ish years only
if ($year -lt ((Get-Date).Year - 1) -or
$year -gt ((Get-Date).Year + 2)
) {
throw "BAD YEAR!"
}
#region
#region destination
# Build up new folder path
$destinationDirectory = Join-Path -Path $destinationDirectory -ChildPath $year
$destinationDirectory = Join-Path -Path $destinationDirectory -ChildPath $month
#Create destination if not exists
if (-not (Test-Path -Path $destinationDirectory)) {
New-Item -Path $destinationDirectory -ItemType Directory | Out-Null
}
#endregion
#region move files
Get-childItem -Path $sourceDirectory -File -Filter $fileFilter |
Move-Item -Destination $destinationDirectory
#engregion
$oldFolder = '\\otnas6uk\sd.test-it.com$\PROJECTS\\Zentic Report'
$jan2018Folder = '\otnas6uk\sd.test-it.com$\PROJECTS'
# Get a list of the files ending with .xlsx
$files = Get-ChildItem $oldFolder | Where { $_.Extension -eq '.xlsx' }
# Move each file over to the new directory
foreach ($file in $files) {
# Repeat if for all months
if ($file.Name -like '*January*' -and $file.Name -like '*2018*') {
$newPath = "$jan2018Folder\$($file.Name)"
}
Move-Item $file $newPath
}
May be this should help move forward:
$Month = "Febuary";
$Year = "2018"
dir .\excelfiles\*$Month*$Year.xlsx|%{move-item -Path $_.FullName -Destination .\Destination.Folder}

File renaming with powershell

Script is working almost how it is intended, still struggling with renaming duplicate files. I cannot figure out how to get it to name the files like
filename(1).ext
filename(2).ext
the closest I have gotten was
filename(1).ext
filename(1)(2).ext
#region actual script
$srcRoot = "C:\srcLocation"
$dstRoot = "C:\dstLocation"
$fileList = Get-ChildItem -Path $srcRoot -File -Force -Recurse
foreach ($file in $fileList) {
$fileName = $file.Name.ToUpper()
$fileExt = $file.Extension.ToUpper()
$dstFileName = $null
switch -Regex ($fileName)
{
'[A-Z]{4}-[0-9]{3}' { $dstFileName = $fileName }
'[A-Z]{4} [0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})\s([0-
9]{3})','$1-$2' }
'[A-Z]{4}[0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})([0-9]
{3})','$1-$2'}
Default { Write-Warning -Message "$fileName is not an expected filename"
}
}
if ($dstFileName) {
$dstDir = $dstFileName.Split('.')[0].Substring(0,8)
$dstPath = Join-Path -Path $dstRoot -ChildPath $dstDir
if (-not (Test-Path -Path $dstPath)) {
New-Item -Path $dstPath -ItemType Directory
}
$i = 1
if (test-path $dstPath\$dstFileName){
$dstFileName = $dstFileName.Split('.')[0] + "($i)" + $fileExt
While (test-path $dstPath\$dstFileName){
$i +=1
$dstFileName = $dstFileName -replace
}
}
Write-Verbose "Moving $($file.FullName)"
Move-Item -Path $($file.FullName) -Destination $dstPath\$dstFileName -
ErrorAction Continue
}
}
#endregion
You can simply use the Replace method of string objects in PowerShell. To verify your input, you can use a RegEx. Move-Item will throw an error, if the file already exists in the destination anyways. The complete script would look like this.
#region setup
New-Item -Path C:\srcpath,C:\dstpath -ItemType Directory
Set-Location C:\srcpath
New-Item 'ABCD123.txt','ABCD 123.txt','AbCD-123.txt','AAAA111.txt','BBBB 222.jpg','BBBB-222.txt' -ItemType File
#endregion
#region actual script
$srcRoot = "C:\srcpath"
$dstRoot = "C:\dstpath"
$fileList = Get-ChildItem -Path $srcRoot -File -Force -Recurse
foreach ($file in $fileList) {
$fileName = $file.Name.ToUpper()
$dstFileName = $null
switch -Regex ($fileName)
{
'[A-Z]{4}-[0-9]{3}' { $dstFileName = $fileName }
'[A-Z]{4} [0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})\s([0-9]{3})','$1-$2' }
'[A-Z]{4}[0-9]{3}' { $dstFileName = $fileName -replace '([A-Z]{4})([0-9]{3})','$1-$2'}
Default { Write-Warning -Message "$fileName is not an expected filename" }
}
if ($dstFileName) {
$dstDir = $dstFileName.Split('.')[0]
$dstPath = Join-Path -Path $dstRoot -ChildPath $dstDir
if (-not (Test-Path -Path $dstPath)) {
New-Item -Path $dstPath -ItemType Directory
}
Write-Verbose "Moving $($file.FullName)"
Move-Item -Path $($file.FullName) -Destination $dstPath\$dstFileName -ErrorAction Continue
}
}
#endregion
#region result
Write-Host '----- Result -----' -BackgroundColor DarkYellow
Get-ChildItem C:\dstpath -Recurse | Select-Object -ExpandProperty FullName
#endregion
Gets the Files in Source folder (Get-ChildItems)
Renames The File to include a - instead of a " " (Rename-Item)
Sets the Child Name property to the new name ($File.Name)
Creates new Folder in source based on first 4 Chars
Moves-Item to new created folder (move-item)
$Source = "C:\Start"
$Destination = "C:\End"
foreach($File in (Get-ChildItem -Path $Source -File -Recurse)){
Rename-Item $File.Fullname ($File.Name -replace " ", "-")
$file.Name = ($File.Name -replace " ", "-")
New-Item "$($Destination)\$($File.Name.Substring(0,3))" -ItemType directory
move-item $File.FullName -force -destination $Destination\$($File.Name.Substring(0,3))
}