My folder structure looks like this:
AK_Data |--->2020-01-22-------|----->a.txt
| |----->b.txt
| |------>c.tf.err
|
|--->2021-01-15-------|----->d.txt
| |----->b.txt
| |------>x.tf.err
|
|--->2022-01-08-------|----->dv.txt
| |----->pq.bat
|
|--->2022-05-08-------|----->xyz.pdf
AK_Data is the first folder which consists of multiple subfolders like (2020-01-22,2021-01-15.....) and these each subfolders contains 1000 of their different format files.
I need to go into each folder and delete all the files except those files having ".tf.err" in their names. I have used $specificdate='2022-01-01' means the files of the folder less than 2022-01-01 only needs to be deleted. So my expected output is:
AK_Data |--->2020-01-22-------|------>c.tf.err
|
|
|
|--->2021-01-15-------|------>x.tf.err
|
|
|
|--->2022-01-08-------|----->dv.txt (this folder will be untouched since>2022-01-01)
| |----->pq.bat
|
|--->2022-05-08-------|----->xyz.pdf (this folder will be untouched since>2022-01-01)
I only need to delete the files inside the folder, not the folder.
The powershell I used for this is:
cls
$specificdate='2022-01-01'
$destination = 'Y:\Data\Retail\ABC\Development\ak\AK_Data'
$files = Get-ChildItem $destination
$exte='\.(bz2)|(.bat)|(.err)|(~)'
foreach ($f in $files){
$outfile = $f.FullName -notmatch $exte
if ($outfile){
if ($f.Name -lt $specificdate){
$allfiles=Get-ChildItem $f.FullName -Exclude *.tf.err* -Name | remove-item -whatif
}
}
}
It is not deleting the files.
I would do this by first iterating the source folder path for directories with a name that can be converted to a datetime less than the datetime in variabe $specificDate.
Then use Get-ChildItem again inside these folders to find and remove files that do not have .tf.err in their name:
$specificdate = [datetime]::ParseExact('2022-01-01','yyyy-MM-dd', $null)
$sourceFolder = 'Y:\Data\Retail\ABC\Development\ak\AK_Data\*'
Get-ChildItem -Path $sourceFolder -Directory |
Where-Object { [datetime]::ParseExact($_.Name,'yyyy-MM-dd', $null) -lt $specificdate } |
ForEach-Object {
Write-Host "Removing files from folder $($_.Name).."
Get-ChildItem -Path $_.FullName -File |
Where-Object { $_.Name -notlike '*.tf.err*' } |
Remove-Item -WhatIf
}
Again here, I added the -WhatIf switch so you can first see what WOULD happen.
If you're OK with that, remove -WhatIf and run the code again to actually delete the files
Related
I want to delete all types of Files from below folder structure which is older than 30 Days. So I used below PowerShell Script. But it is not deleting any file.
PowerShell Script:
Get-ChildItem –Path "C:\Users\VJ\Documents\MainDir" –Recurse | Where-Object { $_.CreationTime –lt (Get-Date).AddDays(-30) } | Remove-Item
Folder Structure:
MainDir
|
SubDir1 -> Folder1 -> Folder2 -> Zip/CSV files
SubDir2 -> Folder1->.txt files
|
Folder2 -> .txt files
End Result should be all types of Files deleted from all folders - subfolders of MainDir.
I think you are confusing the properties CreationTime and LastWriteTime.
If you've just copied (old) files to one of the directories in the structure, the CreationTime is the date and time the file was copied there, which can be today. The LastWriteTime property however shows the date and time the file was last written to.
Try:
$refDate = (Get-Date).AddDays(-30)
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse -File |
Where-Object { $_.LastWriteTime -lt $refDate } |
Remove-Item -Force
If you're on PowerShell version less than 3.0, use:
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse |
Where-Object { !$_.PSIsContainer -and $_.LastWriteTime -lt $refDate } |
Remove-Item -Force
Also, check and retype your dashes, because they may LOOK like normal hyphens, in fact they are EN Dashes (Hex value 2013; Decimal 8211)
Hope that helps
Try this:
Get-ChildItem -Path "C:\Users\VJ\Documents\MainDir" -Recurse -Force | Where-Object { !$_.PSIsContainer -and $_.CreationTime –lt (Get-Date).AddDays(-30) } | Remove-Item -Force
I have a very big folder (contains subfolders in few levels, millions of files in total). I want to only deletes files that are older than X days (eg 10 days).
My script below works fine for a folder with thousands of files, but is not working for that big folder. Any idea to optimize this? Thanks !
$tmpList = Get-ChildItem -Path $sourceFolder -Recurse
$fileObjects = $tmpList `
| Where-Object { !$_.PSIsContainer -and ($_.LastWriteTime -le $maxDateToProcess) } `
| Sort-Object -Property "LastWriteTime" -Descending
$allFiles = $fileObjects | Select -ExpandProperty "FullName"
Remove-Item -Path $allFiles
Type the following command to delete files that haven’t been modified in the last 30 days and press Enter:
Get-ChildItem –Path "C:\path\to\folder" -Recurse | Where-Object {($_.LastWriteTime -lt (Get-Date).AddDays(-30))} | Remove-Item
I have a folder structure with, for example, 100 folders. Each folder has 200 files in it.
I would like to delete (via scheduled task) all files in each folder but keep the last 10 versions of it.
I am trying to upskill in Powershell so I am guessing that this should be pretty simple. I have created this script,
#Delete all files, keep last 10 versions#
$Directory = "D:\Octopus\Packages"
$Keep = "10"
Get-ChildItem $Directory| ?{ $_.PSIsContainer } | Select-Object FullName | Export-Csv $Directory\FolderList.csv
$FolderList = import-csv $Directory\FolderList.csv
ForEach ($row in $FolderList)
{
Get-ChildItem -Recurse | where{-not $_.PsIsContainer}| sort CreationTime -desc | select -Skip $Keep | Remove-Item -Force
}
It appears to be looping through each folder, but keeping the last 10 files for the entire folder structure, not per folder. So some folders have 0 files, some may have 2 files, some may have 8 files.
Any pointers would be appreciated
Thanks !
If you actually need to have that CSV then just modify Get-ChildItem -Recurse to Get-ChildItem $row -recurse. However, if you don't need to be creating the CSV, you can remove of that and just pipe the results of your first Get-ChildItem into the next action.
$Directory = "D:\Octopus\Packages"
$Keep = "10"
Get-ChildItem $Directory| ?{ $_.PSIsContainer } | Select-Object FullName |
ForEach-object {Get-ChildItem $_.fullname -Recurse |
where{-not $_.PsIsContainer}| sort CreationTime -desc |
select -Skip $Keep | Remove-Item -Force }
I have this PowerShell code that compares 2 directories and removes files if the files no longer exist in the source directory.
For example say I have Folder 1 & Folder 2. I want to compare Folder 1 with Folder 2, If a file doesn't exist anymore in Folder 1 it will remove it from Folder 2.
this code works ok but I have a problem where it also picks up file differences on the date/time. I only want it to pick up a difference if the file doesn't exist anymore in Folder 1.
Compare-Object $source $destination -Property Name -PassThru | Where-Object {$_.SideIndicator -eq "=>"} | % {
if(-not $_.FullName.PSIsContainer) {
UPDATE-LOG "File: $($_.FullName) has been removed from source"
Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue
}
}
Is there an extra Where-Object {$file1 <> $file2} or something like that.?
I am not sure how you are getting the information for $source and $destination I am assuming you are using Get-ChildItem
What i would do to eliminate the issue with date/time would be to not capture it in these variables. For Example:
$source = Get-ChildItem C:\temp\Folder1 -Recurse | select -ExpandProperty FullName
$destination = Get-ChildItem C:\temp\Folder2 -Recurse | select -ExpandProperty FullName
By doing this you only get the FullName Property for each object that is a child item not the date/time.
You would need to change some of the script after doing this for it to still work.
If I am not getting it wrong, the issue is your code is deleting the file with different time-stamp as compared to source:
Did you try -ExcludeProperty?
$source = Get-ChildItem "E:\New folder" -Recurse | select -ExcludeProperty Date
The following script can serve your purpose
$Item1=Get-ChildItem 'SourcePath'
$Item2=Get-ChildItem 'DestinationPath'
$DifferenceItem=Compare-Object $Item1 $Item2
$ItemToBeDeleted=$DifferenceItem | where {$_.SideIndicator -eq "=>" }
foreach ($item in $ItemToBeDeleted)
{
$FullPath=$item.InputObject.FullName
Remove-Item $FullPath -Force
}
Try something like this
In PowerShell V5:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 -file).Name
gci $yourdir2 -file | where Name -notin $filesnamedir1| remove-item
In old PowerShell:
$yourdir1="c:\temp"
$yourdir2="c:\temp2"
$filesnamedir1=(gci $yourdir1 | where {$_.psiscontainer -eq $false}).Name
gci $yourdir2 | where {$_.psiscontainer -eq $false -and $_.Name -notin $filesnamedir1} | remove-item
If you want to compare files in multiple dir, use the -recurse option for every gci command.
I'm trying to write a script that deletes all folders that are older than 60 days and create a logfile with the folder names in the directory where the folders have been deleted.
What I have now is:
Get-ChildItem -Directory -Path "\\share\dir1\dir2" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-10) } |
Remove-Item -Force -Recurse | Out-File Auto_Clean.log -Append -WhatIf
The output stays like this for ages:
What if: Performing the operation "Output to File" on target "C:\users\bgijbels\Downloads\Auto_Clean.log".
When I remove the part for Out-File it works fine. It seems like the Out-File part is trying to write the name of every file in the folder to the log, while I only need to have the folder name. I think that's why it takes so long, if at all it gets past the part of creating the logfile. Any ideas? Thank you for your help.
You are getting a list of all files because -Recurse switch enumerates contents of folders so it can be deleted prior to the root folder removal. Try this:
Get-ChildItem -Directory -Path "\\share\dir1\dir2" |
Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-60) } | % {
$folder = $_;
Remove-Item $folder.FullName -Force -Recurse | Out-Null
$folder.FullName } |
Out-File Auto_Clean.log -Append -WhatIf
Directory object is kept as $folder var and you effectively echo its full path after deletion. Obviously take -WhatIf off the end after you are happy with results.