1

Need help with command like, one-liner, powershell to remove folders I'm trying to find an elegant way to remove folders by folder name which reflects the date but I cannot rely on the file/folder date meta-data attributes.

Here's the problem I'm trying to solve: I have a folder in which there are archived call recordings for each day the recording system creates folders and fills them with call recordings, a folder for each day named like format MM_dd_yyyy. I need to remove all but the last 7 folders. But, I cannot rely on the creation/modified date on the file. That would be much easier with just powershell. So I MUST, unfortunately, remove the folders by testing the file name against the dates of the folders that I need to retain with same format (MM_dd_yyyy). I can get the list of folder names that are to be retained base on the previous 6 days with the following Windows command line:

c:\>powershell $d0=(Get-Date).ToString('MM-dd-yyyy'); $d1=(Get-Date).AddDays(-1).ToString('MM-dd-yyyy'); $d2=(Get-Date).AddDays(-2).ToString('MM-dd-yyyy'); $d3=(Get-Date).AddDays(-3).ToString('MM-dd-yyyy'); $d4=(Get-Date).AddDays(-4).ToString('MM-dd-yyyy'); $d5=(Get-Date).AddDays(-5).ToString('MM-dd-yyyy'); $d6=(Get-Date).AddDays(-6).ToString('MM-dd-yyyy'); $d0; $d1; $d2; $d3; $d4; $d5; $d6

NOTE: I need to keep this in a command one-liner and cannot use PS1 power shell script because of corporate and domain enforced security limitations

This produces the folder names to be retained as listed below (ran on 20 NOV 2021 to retain last 7 days).

11_20_2021
11_19_2021
11_18_2021
11_17_2021
11_16_2021
11_15_2021
11_14_2021

The intention would be to remove any folder names that were like 11_13_2021, 11_12_2021... etc.

I can get away with running nested FOR loops in a Windows bat file to try and hack this together but I'm trying to find a more simple, readable and elegant one-liner that will let me do something like the following: powershell $d=(Get-Date).AddDays(-7).ToString('MM-dd-yyyy'); and then some magic powershell stuff to remove any folder that doesn't match any of those that are to be retained.

If I had a way to provide the folder name (MM_dd_yyyy) to the (get-date).AddDays(-6) powershell command and have it return a boolean yes or no, that would be something closer to what I'm looking for. I've been reading and you tubing and pulling hairs out but so far I'm learning but mostly making a mess of it. Any ideas are most welcome.

I'm likely approaching this all wrong. The constraints are:

Given a list of folders with naming format MM_dd_yyyy, I need to remove/delete all that are not within the last week of days.

I cannot run powershell scripts .ps1 I can run windows bat or cmd files with for loops and such I cannot rely on the folder of files date/time meta attributes, some data in the folders may have create/write/modified dates that are not in line with the folder name. I must rely on the folder name (MM_dd_yyyy) to remove the folders.

UPDATED with resolution:

powershell "($f=Get-ChildItem -Path 'D:\PosConvSav' -Filter '*_*_*' -Directory | Where-Object { $_.Name -match '\d{2}_\d{2}_\d{4}' } | sort-object -desc)[14..($_.count)] | remove-item -recurse"
James
  • 63
  • 9
  • 1
    Why is a one liner more secure than a two or more liner or a script? – Olaf Nov 20 '21 at 07:40
  • Why can't you run powershell scripts but apparently you can run a bat that call upon PowerShell? – Theo Nov 20 '21 at 12:52
  • The owners of the system I'm working on does not allow me to use any PS1 or vbs. I could but I'd be risking myself. Generally if I can pull it off in a one-liner, even if it calls on powershell or wmic, I can get away with it. It is more of a culture restriction than a hard enforced restriction. When I become more aware and competent with powershell, I'll be able to defend the use of my tools better. – James Nov 20 '21 at 17:07

1 Answers1

5

The PowerShell code for this would be:

Get-ChildItem -Path 'RootPath\Where\The\Folders\To\Delete\Are\Found' -Filter '*_*_*' -Directory |
    Where-Object { $_.Name -match '\d{2}_\d{2}_\d{4}' } |                   # filter some more using regex -match
    Sort-Object { [datetime]::ParseExact($_.Name, 'MM_dd_yyyy', $null) } |  # sort by date
    Select-Object -SkipLast 7 |                                             # skip the newest 7 folders
    Remove-Item -Recurse -Force                                             # remove the rest

To play it safe, add -WhatIf to the final Remove-Item command. By doing that, the code does not actually delete anything, but show in the console what would be deleted. If you are satisfied that is correct, then remove -WhatIf to actually remove those folders.

As Olaf already commented, don't think using one-line code would be best, because what you'll end up with is code that isn't readable anymore and where mistakes are extremely hard to find. There is no penalty whatsoever for multiline code, in fact it is THE way to go!

Theo
  • 57,719
  • 8
  • 24
  • 41
  • 1
    Sort-Object requires the -Descending parameter to keep the newest folders. – nimizen Nov 20 '21 at 14:00
  • 1
    @nimizen Ah yes, stupid of me.. Either sort Descending or use `-SkipLast`. Fixed now – Theo Nov 20 '21 at 15:04
  • Thanks for the help. With your input, I learned some useful things and eventually ended up with the one-liner that I just updated to the end of the post description. – James Dec 05 '21 at 06:01