I see below two methods doing the same operation in Power Shell, which is preferred method to remove the file older than 1 day?
Option 1:
Get-ChildItem -Path c:\temp -File | ?{($_.LastWriteTime -lt (Get-Date).AddDays(-1)) -and ($_.Name -like "a*") -and ($_.Extension -eq ".csv")} | Select-Object –ExpandProperty FullName | %{Remove-Item $_ -Force -WhatIf}
Option 2
Get-ChildItem -Path c:\temp -Filter "a*.csv" -File | Where LastWriteTime -lt (Get-Date).AddDays(-1) | Remove-Item -Force -WhatIf
Thanks
SR
Option 2.
? and where are aliases for the where-object cmdlet. filtering aside, they both are checking if the LastWriteTime is older then 24hours in the same way.
As stated by HAL9256 if you need to filter, you should do that first.
If you need more fancy filtering (e.g. regex ), filtering with where-object is the next best thing.
Go with Option 2 because you always want to filter before continuing with the pipeline. Dealing with less data ahead of time in pipelines will always be better.
Option 1 will get every file object (e.g. 100's of files) to pass down the pipeline before it can begin to look at applying the where clause.
Option 2 will filter "a*.csv" files, which should always get you fewer files (e.g. 10's), before continuing down the pipeline to apply the where clause.
I would do it this way.
get-childitem | where { (get-date) - $_.lastwritetime -gt '1' } | remove-item -whatif
Related
Just wrote Powershell script that will look in Sub-Folder about the file which include ".doc_" in it's name that created 1 Min ago then to move it to another Sub-Folder.
When I ran the powershell script it will move that file which having ".doc_" in it's name that created 1 Min ago but also it will move same files which had ".doc_" in it's name that created days ago which is not required.
Could you please let me know why my code take in consideration files which is more than 1 Min
get-childitem -Path "C:\Users\Administrator\Desktop\Test\Test2" | where-object {$_.Name -match ".doc_" -and $_.LastWriteTime -lt (get-date).Adddays(-0) -and $_.LastWriteTime -lt (get-date).AddMinutes(-1)}| move-item -destination "C:\Users\Administrator\Desktop\Test"
In short, your filter for Get-Date is wrong in the sense of it grabbing everything before 1 minute ago. This is due to the -lt operator, which should work if you swap it with the -gt operator.
Okay, next subject. Since you're not actually searching for specific words inside files, but instead in the file names, we can use the FileSystem Provider to filter for that file name, which we will sacrifice RegEx (using -match), to using wildcard expressions; this will speed things up to 40x faster as sending anything down the pipeline is quite expensive:
Get-ChildItem -Path "C:\Users\Administrator\Desktop\Test\Test2" -Filter "*.doc_*" |
where-object { $_.LastWriteTime -gt (Get-Date).AddMinutes(-1) } |
Move-Item -Destination "C:\Users\Administrator\Desktop\Test"
And if time is of the essence, we can try avoiding the pipeline using the the grouping operator ( .. ), and the .Where({}) operator/method.
It's considered more of an operator due to the fact that it doesn't perform any direct action against the object(s) themselves.
(Get-ChildItem -Path "C:\Users\Administrator\Desktop\Test\Test2" -Filter "*.doc_*").Where{
$_.LastWriteTime -gt (Get-Date).AddMinutes(-1)
} | Move-Item -Destination "C:\Users\Administrator\Desktop\Test"
I need a powershell script ;
it must search some subfolders which folders names are starting with character between 1 and 6 (like 1xxxx or 2xxx)
and using the name of these folders as variable it must look under each folder for the *.XML files which are older than 30 min
and if it finds them it must delete it.
there may be more than one folder at same time, which are providing the same conditions so IMO using an array is a good choice. But I'm always open to other ideas.
Anybody can help me please ?
Basically I was using this before the need changes but now it doesnt help me.
powershell -nologo -command Get-ChildItem -Path C:\geniusopen\inbox\000\ready\processed | Where CreationTime -lt (Get-Date).AddDays(-10) | remove-item
Thank you
You can do something like the following and just remove -WhatIf if you are satisfied with the results:
$Time = (Get-Date).AddMinutes(-30)
Get-ChildItem -Path 'C:\MostCommonLeaf' -Recurse -File -Filter '*.xml' |
Where {$_.CreationTime -lt $Time -and (Split-Path $_.DirectoryName -Leaf) -match '^[1-6]' -and $_.Extension -eq '.xml'} |
Remove-Item -WhatIf
MostCommonLeaf would be the lowest level folder that could start as your root search node. We essentially don't want to traverse directories for nothing.
You could potentially make the script above better if you know more about your directory structure. For example, if it is predictable within the path where the 1xxx folders will be, you can construct the -Path parameter to use the [1-6] range wildcard. -Filter '*.xml' could also return .xmls files for example, so that's why there is additional extension condition in the Where.
Using -Recurse and -Include together generally results in much slower queries. So even if tempted, I would avoid a solution that uses those together.
If there are millions of files/directories, a different command construction could be better. Running Split-Path millions of times could be less efficient than just matching on the directory name, e.g. where {$_.DirectoryName -match '\\[1-6][^\\]*$'}.
I think you are looking for something like this:
$limit = (Get-Date).AddMinutes(-30)
$path = "C:\Users\you\xxx"
$Extension = "*.xml"
Get-ChildItem -Path $path -Filter $Extension -Force | Where-Object {$_.CreationTime -lt $limit} | Remove-Item
I haven't tested it though.
Keep in mind whether you need: $.CreationTime or $.LastWriteTime
I am new to powershell, but have been successful putting together from various searches, the way to remove files of a certain age, within a specific folder.
My issue is that now within that specific folder, I now need to only remove certain file names, and not ALL files older than a specific date.
The script I am currently using is:
$limit = (Get-Date).AddDays(-14)
$path = "C:\Folder\Files-in-specific-folder"
# Delete files older than the $limit.
Get-ChildItem -Path $path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
This works great to just delete files older that 14 days, but how do I add say a wildcard that it uses to ONLY delete files with the name web in it?
Thanks much!
Mike
When entering a script block for where-object, or any function that will process a script block. You can have multiple instances as long as you clearly seperate them.
For example:
Get-Command | Where-Object {($_.Name -like '*clear*') -and ($_.CommandType -eq 'cmdlet')}
So for your script just apply the same concept and add a name Filter to your existing Filter:
Get-ChildItem -Path $path -Recurse -Force | Where-Object { ($_.Name -like "*web*") -and (!$_.PSIsContainer -and $_.CreationTime -lt $limit) } | Remove-Item -Force
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
I am trying to create a CSV file of all jpgs in a directory and its sub-directories that are above 100 KB and have the suffix "_lowRes.jpg".
Want to use Powershell.
Any help please?
This is pretty easy actually!
You'll do this with two separate filters, which PowerShell achieves via the Where-Object cmdlet. This cmdlet accepts comparisons in the format of {$_.PropertyName -eq "Something"} or PropertyName -eq "Something". The later format is only available on PowerShell v3 and up.
First, to filter to only files above 100KB.
Where-Object Length -ge 100KB
The second part, where the filename contains something.
Where-object Name -like "*lowRes.jpg*"
You could join them, but I would just pipe one into the other, like this.
dir *.jpg -Recurse | Where-Object Length -ge 100KB | Where-object Name -like "*lowRes.jpg*"
You might want to put the Name filtering first, because less files will have a certain name than be above or below a certain size. Depends on how your files are laid out.
Finally, pipe all of that into the Export-Csv cmdlet and bam, you're done!
you can do it simply like this :
Get-ChildItem "C:\temp" -Recurse -file -filter "*_lowRes.jpg" |
Where Length -ge 100KB | select fullname, Length |
export-csv "c:\temp\result.csv" -NoType
short version (for no purist) :
gci "C:\temp" -Rec -file -filter "*_lowRes.jpg" | ? L -le 100KB | select fu*, le* | epcsv "c:\temp\result.csv" -Not