How can I delete folders, not files, using PowerShell? I want to delete folders that are over 3 days old.
Get-ChildItem "D:\test" |
Where-Object { $_.PSIsContainer -and $_.LastWriteTime -le (Get-Date).AddDays(-3) } |
ForEach-Object { Remove-Item $_ -Force }
This doesn't work. I get no error and it does not delete any folders that are within d:\test.
Try:
Get-ChildItem "D:\test" |
Where-Object { $_.PSIsContainer -and $_.LastWriteTime -le (Get-Date).AddDays(-3) } |
Remove-Item -Force
or:
Get-ChildItem "D:\test" |
Where-Object { $_.PSIsContainer -and $_.LastWriteTime -le (Get-Date).AddDays(-3) } |
ForEach-Object { Remove-Item $_.FullName -Force }
Assuming your using powershell 4+ you don't need to do all the fancy filtering, the -file switch will give you what you need.
Get-ChildItem -Path D:\test -File | Remove-Item
The above will give you what you need.
Related
I'm sure I've missed something obvious, but it's been a while since I have needed to use PowerShell (n.b. it is version 2).
I need a basic script that deletes files over a certain age (3 days). I have the following:
$logDirectory = "C:\logs\"
$days = (Get-Date).AddDays(-3)
# Delete files older than the $days
Get-ChildItem -Path $logDirectory -Recurse |
Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $days } |
%{Write-Host File Found: $_.fullname $_.LastWriteTime}
Get-ChildItem -Path $logDirectory -Recurse |
Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $days } |
Remove-Item -Force
This works, but If I combine the two it doesn't. And I'm sure there must be a neater way to do this where I can write out a list of files, and then delete them. Something like:
Get-ChildItem -Path $logDirectory -Recurse |
Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $days } |
%{Write-Host File Found: $_.fullname $_.LastWriteTime} |
Remove-Item -Force
But all this does is list the items, not delete them.
I'm trying to find a way to get my script to print out a log file of what files are actually being deleted. Does anyone know how I could go about doing this? Here is my screen I would like to add that onto.
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } |
Remove-Item -Force
Unfortunately, the Remove-Item cmdlet doesn't support the -Passthru parameter, which might make this easier. However, you could do this:
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } |
Tee-Object -FilePath .\Log.txt |
Remove-Item -Force
But that's a bit ugly because it outputs the directory listing from Get-ChildItem. You could do this instead to capture just the paths:
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } |
Select-Object -ExpandProperty FullName |
Tee-Object -FilePath .\Log.txt |
Remove-Item -Force
Also, note that if you're using PowerShell v3.0 or later, the Get-ChildItem cmdlet supports the -File and -Directory parameters, so you don't need to do the whole -not $_.PsIsContainer stuff.
The overall easiest way if you just need a log would be to use a Transcript and Verbose Output.
your script would look like this, make sure you pay attention to the addition of -Verbose to your command.
Start-Transcript C:\Logs\Remove.txt
Some-Command | Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } | Remove-Item -Force -Verbose
Stop-Transcript
then the C:\Logs\Remove.txt file will have a message like this for each removed file:
VERBOSE: Performing the operation "Remove File" on target "H:\dns.csv".
You would need a loop:
Get-ChildItem -Path $Targets |
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } |
ForEach-Object {
$_ | Remove-Item -Force
$_.FullName | Out-File -FilePath $LogFile -Append
}
Simplest way to write output to log file is by using -Verbose and then use Write-Verbose or 4> after the command
Where-Object { -not $_.PSIsContainer -and $_.LastWriteTime -lt (Get-Date).AddDays(-1) } | Remove-Item -Verbose 4> $log_file_path
I wrote a simple script that will run as a scheduled task every weekend. This script cleans up files older than # days and you can give the name of a folder for exclusion as a parameter. This folder should not be cleaned up by the script. But somehow the script still deletes some files from the excluded folder. But in a strange way no files matching the conditions of the parameter.
For example I run the script to delete files older than 15 days and exclude the folder NOCLEANUP. but some files still get deleted from that folder, but there are still files older than 15 days in the NOCLEANUP folder.
Code below
Thanks in advance and apologies for the dirty code. Still new to PS.
Function CleanDir ($dir, $days, $exclude, $logpath)
{
$Limit = (Get-Date).AddDays(-$days)
$Path = $dir
#Folder to exclude
$ToExclude = $exclude
#Log location
$Log= $logpath
$Testpath = Test-Path -PathType Container -Path $Log
if ($Testpath -ne $true)
{
New-Item -ItemType Directory -Force -Path $Log
}
#Logs deleted files
cd $Log
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastwriteTime -lt $Limit } | Where-Object { $_.fullname -notmatch $ToExclude} | Where-Object { $_.fullname -notmatch '$RECYCLE.BIN'} | Out-File -FilePath CLEANUPLOG.TXT
# Delete files older than the $Limit.
Get-ChildItem -Path $Path -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.LastwriteTime -lt $Limit } | Where-Object { $_.fullname -notlike $ToExclude} | Remove-Item -Force -Recurse
#Goes into every folder separately and deletes all empty subdirectorys without deleting the root folders.
$Folder = Get-ChildItem -Path $Path -Directory
$Folder.fullname | ForEach-Object
{
Get-ChildItem -Path $_ -Recurse -Force | Where-Object {$_.PSIsContainer -eq $True} | Where-Object {$_.GetFiles().Count -eq 0} | Remove-Item -Force -Recurse
}
}
Can anybody help me please in writing the below Powershell commands as a batch file? I will execute the file by command prompt. I don't have the option of creating a ps1 file and executing it through the command prompt.
Thank you.
$limit = (Get-Date).AddDays(-4)
$path = "T:\FolderName"
Get-ChildItem -Path $path -Recurse -Force -include *.txt | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force
Get-ChildItem \\123.456.78.910\Y$\Z\*.txt | Where { $_.CreationTime -ge (Get-Date).AddMinutes(-30) } | % { Copy-Item $_.FullName -destination T:\FolderName }
You can invoke powershell.exe with the -command parameter to do this. You can also have more than one powershell command by separating them with semicolon. You should double-double-quote any double-quotes.
Here's an example:
powershell -command "$limit = (Get-Date).AddDays(-4); $path = 'T:\Folder Name';Get-ChildItem -Path $path -Recurse -Force -include *.txt | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force"
powershell -command "$limit = (Get-Date).AddDays(-4); $path = 'T:\Folder Name';Get-ChildItem \\123.456.78.910\Y$\Z\*.txt | Where-Object { $_.CreationTime -ge (Get-Date).AddMinutes(-30) } | % { Copy-Item $_.FullName -destination 'T:\DestinationFolderName' }"
EDIT:
Here is a one-line version of it with only a single set of ""; all quotes inside are single '
powershell -command "$limit = (Get-Date).AddDays(-2); $path = 'D:\Folder\Folder Name'; Get-ChildItem -Path $path -Recurse -Force -include *.txt | Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt $limit } | Remove-Item -Force;Get-ChildItem \\123.456.25.123\D$\folder*.txt | Where-Object { $_.CreationTime -ge (Get-Date).AddMinutes(-30) } | % { Copy-Item $_.FullName -destination 'D:\Folder\Folder' }";
With these lines of code:
get-childitem -Path d:\scripts –recurse |
where-object {$_.lastwritetime -gt (get-date).addDays(-1)} |
Foreach-Object { $_.FullName }
I get a list of everything under the d:\scripts directory that is less than 1 day old in time stamp. Output:
D:\scripts\Data_Files
D:\scripts\Power_Shell
D:\scripts\Data_Files\BackUp_Test.txt
D:\scripts\Power_Shell\archive_test_1dayInterval.ps1
D:\scripts\Power_Shell\stop_outlook.ps1
D:\scripts\Power_Shell\test.ps1
D:\scripts\WinZip\test.wjf
The deal is, the file folders (Data_Files & Power_Shell) have a last write with in the date param. I just want the files as in lines 3 - 7 in output.
Suggestions?
get-childitem -Path d:\scripts –recurse |
where-object {$_.lastwritetime -gt (get-date).addDays(-1)} |
where-object {-not $_.PSIsContainer} |
Foreach-Object { $_.FullName }
$_.PSIsContainer is true for folders, allowing the extra where-object filters them out.
gci d:\scripts –recurse |
? { $_.Attributes -band [System.IO.FileAttributes]::Archive } |
? { $_.LastWriteTime -gt (Get-Date).AddDays(-1) } |
foreach { $_.FullName }
or
gci d:\scripts –recurse |
? { -not ($_.Attributes -band [System.IO.FileAttributes]::Directory) } |
? { $_.LastWriteTime -gt (Get-Date).AddDays(-1) } |
foreach { $_.FullName }
Try this:
dir d:\scripts –recurse | where {!$_.PSIsContainer -AND $_.lastwritetime -gt (get-date).addDays(-1)} | foreach { $_.FullName }
List all files in all subdirectories and sort them by LastWriteTime (newest write at the end):
Get-ChildItem -Recurse | Sort-Object -Property LastWriteTime | Select-Object LastWriteTime,FullName