I am trying to delete all folders that are passed 30 days old but I need to base it off of the folder name instead of the creation date. Files get generated and put into a folder with the month on it and inside of it the Month date and year. The Month format is like this MM yyyy and month date like MMddyyyy. I had a script working in powershell v2 that worked well but stopped working in powershell V3.
This was my V2 script
function Delete-Folder-30days
$today = get-date -displayhint date
$30days = (get-date).AddDays(-30)
$folders = (gci "\\$args\Apps\AndrewTest" | where-object {$_.PSIsContainer -eq $True})
foreach ($f in $folders) {
$folderdate = get-date -mont $f.Name.substring(0,2) -day $f.Name.substring(2,2) -year $f.Name.substring(4,2)
if ($folderdate)
{
Remove-Item "\\$args\Apps\AndrewTest\$f" -recurse
}
}
}
Delete-Folder-30days $Server
What could i be doing wrong here?
Thanks,
Andrew
Try using the [DateTime]::ParseExact() method, it's much simpler for your purposes:
function Delete-Folder-30days{
gci "\\$args\Apps\AndrewTest" -Directory | ?{[datetime]::ParseExact($_.Name,"MMddyyyy",$null) -lt (get-date).AddDays(-30)} | Remove-Item -Recurse
}
Delete-Folder-30days $Server
Edit: Sorry! Had the String and Format switched (should be like ("04122014","MMddyyyy",$null)) but I had the first two arguments reversed.
Edit2: You want it to include .zip files as well? There's a couple of things. If you want to include all files then it is really simple. Just remove the -Directory from the GCI command and it will look at all files and folders in the target directory. If you ONLY want folders and .ZIP files then it gets a little more complicated. Basically we will still remove the -Directory switch, but we'll have to add some filtering into the Where clause as such:
?{($_.PSIsContainer -and [datetime]::ParseExact($_.Name,"MMddyyyy",$null) -lt (get-date).AddDays(-30)) -or ($_.Extension -ieq ".zip" -and [datetime]::ParseExact($_.BaseName,"MMddyyyy",$null) -lt (get-date).AddDays(-30))}
So now instead of just checking the specially formatted date, you are asking Is this a folder, or does it have the .zip file extension? If at least one of those two is true, does it match the specially formatted date?
Related
We're on sort of a file timecrunch. There are a bunch of files from 4/9/2019 that we need out of a bunch of directories. Every directory has ~1000 files. We want to copy all those files from 4/9/2019 to their respective folder structures, but only those files.
We used xcopy to copy the folder structure and have been manually copying the files we need. However, there are 1000 folders each with ~1000 files so it makes quite the hurdle. Tried passing on our arguments to copy-item, but it hasn't been giving me much luck.
I'm assuming even with my garbled code that there's some easy parameter or something I overlooked. We've been working through break and I've browsed through many topics and am turning to the community for help. I probably passed my exact problem on the way here.
For the record I don't code and use PowerShell infrequently.
#Gets all files that were last modified on 4/9/2019
(Get-ChildItem -Recurse | Where-Object {$_.LastWriteTime -gt (Get-Date -month 4 -day 9 -Format d) -and $_.LastWriteTime -lt (Get-Date -month 4 -day 10 -Format d)}) |
#Copies the files from source to destination
Copy-Item "C:\abc\" "D:\abc\"
}
When working with [datetime] type variables don't apply -format D this converts to a string,
instead strip the time component by appending .Date to both sides and test for equality.
As you are recursing the source into subfolders, you can't specify a flat target
$Source = "C:\abc\"
$Target = "D:\abc\"
$MyDate = (Get-Date -Month 4 -Day 9 -Year 2019).Date
Get-ChildItem -Path $Src -Recurse |
Where-Object {$_.LastWriteTime.Date -eq $MyDate} | ForEach-Object{
$TargetDir = $_.DirectoryName.replace($Source,$Target)
If (!(Test-Path $TargetDir)){New-Item $TargetDir -ItemType Directory|Out-Null}
$_ | Copy-Item -Destination $TargetDir
}
Untested, you might append the -WhatIf parameter to Copy-Item while testing.
Robocopy is for sure faster, once you've found the right parameters.
I'm trying to create a batch (or PowerShell) script that does the following:
Gets the current date (i.e. 06/21/2018)
Looks at all sub-folders in a specific folder (not recursively, just the immediate sub-folders) and finds all folders with a created date in the previous year, up to the current date in the previous year (i.e. 01/01/2017 - 06/21/2017).
Moves all of those folders to a '2017 Jobs' folder.
So I've been searching around for an answer to this question but everything seems to be focused around file dates, not folder dates, so here we are. I know how to use Robocopy to move the folders once found, but all of it's switches are based around moving files older than X date, not folders. Any ideas on how I can achieve a folder-based created date looping lookup?
Without building the entire script for you, here are your pieces:
$date = Get-Date
$dateAYearAgo = $date.AddYears(-1)
$items = Get-ChildItem "C:\base\folder" | Where-Object {$_.CreationTime -gt $start -and $_.CreationTime -lt $end}
$items | Move-Item "C:\base\folder\2017 Jobs"
As for filtering out just folders, you can see if the version of powershell you are on allows Get-ChildItem C:\ -Directory to pull only directories, or you can use Get-ChildItem C:\ | Where-Object { $_.PSIsContainer }
I am trying to incorporate Powershell into my everyday workflow so I can move up from a Desktop Support guy to a Systems Admin. One question that I encountered when helping a coworker was how to search for a lost or forgotten file saved in an unknown directory. The pipeline I came up with was:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Out-File pdfs.txt
This code performed exactly how I wanted but now I want to extend this command and make it more efficient. Especially since my company has clients with very messy file management.
What I want to do with this pipeline:
Recursively search for a specific file-type that was created in a specified time-frame. Lets say the oldest file allowed in this search is a file from two days ago.
Save the file to a text file with the columns containing the Filename, FullName(Path), and sorted by the created time in descending order.
What I have so far:
dir C:\ -Recurse -Filter *.pdf -ErrorAction SilentlyContinue -Force | Select-Object Name, FullName | Out-File *pdfs.txt
I really need help on how to create a filter for the time that the file was created. I think I need to use the Where-Object cmdlet right after the dir pipe and before the Select Object pipe but I don't know how to set that up. This is what I wrote: Where-Object {$_.CreationTime <
You're on the right track, to get the files from a specific file creation date range, you can pipe the dir command results to:
Where-Object {$_.CreationTime -ge "06/20/2017" -and $_.CreationTime -le "06/22/2017"}
If you want something more repeatable where you don't have to hard-code the dates everytime and just want to search for files from up to 2 days ago you can set variables:
$today = (Get-Date)
$daysago = (Get-Date).AddDays(-2)
then plugin the variables:
Where-Object {$_.CreationTime -ge $daysago -and $_.CreationTime -le $today}
I'm not near my Windows PC to test this but I think it should work!
See if this helps
dir c:\ -Recurse -Filter *.ps1 -ErrorAction SilentlyContinue -Force | select LastWriteTime,Name | Where-Object {$_.LastWriteTime -ge [DateTime]::Now.AddDays(-2) } | Out-File Temp.txt
Hello,
As i said before in the title, i would like to make a script who :
Only scan the directories
Scan the name of the directory ex.(ABC_20170504_12H03) and extract only the date (20170504).
Compare the date extracted before with the actual date minus 3 months.
Remove the directory if the date contained in the folder name is older than 3 months.
The problem is that i'm just starting to learn PowerShell, and this is my first task using this language. I'm a little bit lost and i would really appreciate some help.
Thank you.
Get-ChildItem -Path "C:\path" -Recurse | Where-Object { $_.PsIsContainer } | ForEach-Object {
if((Get-Date).AddMonths(-3) -gt [DateTime]::ParseExact($_.Name.Split("_")[1], "yyyyddMM", $null)) {
Remove-Item -Path $_.FullName -WhatIf
}
}
stackoverflow,
I am trying to come up with a PoSh script to do a very specific task that has me beating my head against my desk here. I am pretty new to Powershell, and need some help here.
Here is what I am trying to accomplish:
I need to be able to search through a drive for a specific folder called "30 Day Toss" and delete any subfolder(s) inside of it that has a creationdate of over 30 days old.
Example:
P:\Project\2014\3D1004\Plan 1\30 Day Toss\Archive1
P:\Project\2014\3D1004\Plan 2\30 Day Toss\04-12-2014
The Archive1 folder above was created 10 days ago and doesn't need deleted.
The 04-12-2014 folder above was created over 30 days ago and needs deleted, along with all files/folders under it.
The Project, year, job number and plan number are all variable and change, so hard coding a search path isn't an option.
Any assistance would be greatly appricieated, thanks!
Ok, so assuming that your folder structure is always the same, and you always want the 6th level of folder or subfolders of that, this will work:
gci P:\ -directory -recurse | ?{$_.FullName -match ".:\\.+?\\.+?\\.+?\\.+?\\.+?\\" -and $_.CreationTime -lt (get-date).AddDays(-30)}|Remove-Item -recurse -whatif
That looks at the entire P: drive for folders, if the folder name is:
P:\<anything>\<anything>\<anything>\<anything>\<anything>\<anything>
It checks to see if it was created over 30 days ago, and if so it deletes it and all of it's contents. But it has to have that many levels for the script to look at it.
Edit: Ok, let's change it up a little. If the folder we're looking inside of is always called "30 Day Toss" we'll look for all folders with that name, and then pull a listing of things inside each of them. Easy enough! First, the code:
gci P:\ -Directory -Recurse | ?{$_.Name -ieq "30 Day Toss"} | %{GCI $_.FullName | ?{$_.CreationTime -lt (get-date).AddDays(-30)} | Remove-Item -Recurse -Force}
Then to break it down a little.
First we get a listing of all folders on the P: drive. Then we select only the ones named "30 day toss" (not case sensitive).
For each folder we find with that name we pull a directory listing for whatever is inside that folder, and then select only the things older than 30 days. For each of those things that are older than 30 days we delete them, and anything inside them.
$date = (get-date).AddDays(-30)
$folders = gci "p:\" -filter "30 Day Toss" -recurse
Foreach ($subfolder in $folders.FullName) { gci $subfolder | where {$_.psiscontainer} | where { $_.CreationTime -lt $date} | remove-item -force -recurse }