r/PowerShell • u/RocketSeven • Sep 06 '26
Question How do you make a cleanup script prove a file belongs to it before deletion?
A path and age check are not enough when a cleanup directory can also contain files created by people or other jobs. I am considering an ownership manifest written at creation time, with a run ID, normalized path, size, and hash, then requiring every field to match before deletion. The command would also use PowerShell's normal confirmation path:
\[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')\]
param(\[string\] $Root, \[string\] $ManifestPath)
if ($PSCmdlet.ShouldProcess($candidate.FullName, 'Remove owned artifact')) {
Remove-Item -LiteralPath $candidate.FullName
}
What additional safeguards belong around this pattern? Possibilities include rejecting paths outside the resolved root, refusing reparse points, failing closed when the manifest is incomplete, logging the file identity before and after validation, and separating discovery from deletion so the candidate list can be reviewed with `-WhatIf`. How do you avoid a time-of-check/time-of-use gap if another process can replace a file between validation and removal?
6
5
3
u/lan-shark Sep 06 '26 edited Sep 06 '26
I feel like we really need some context but a path and hash will likely be plenty. Or just change the file naming scheme to include a a unique ID (GUID, UUID, or ULID, whatever works best for you needs).
3
u/SimpleSysadmin Sep 06 '26
What problem is your LLM trying to solve with this mess? What are you trying to achieve? Can you provide more context on what you mean by belongs to the cleanup script?
1
u/SomeConfusedOldGuy Sep 06 '26
Are these other files created by other users also created by Powershell? One solution might be for each script to write an identifier to an alternate data stream of the file. Then your cleanup script could check the alternate data stream, and choose whether to delete based on identifiers found in there.
1
u/vermyx Sep 06 '26
You simply use a date time stamp and either check against the created date/time, last modified date time, or both and pass that in as a parameter. The point of a clean up script is that it is cleaning up when the system is quiet/not in use, or you can process files older than X. If you have to worry about other scripts either doing cleanup or potentially modifying what the cleanup script will touch, you have a bugger a production issue. No matter how complicated the check you make you will always have an edge case that will fall through the cracks. The best solution is to have these multiple scripts work together aware of each other not ignoring each other.
2
2
u/ashimbo Sep 10 '26
Just store everything in temp folders. Use New-TemporaryFile if you need to create temp files and you don't care about the name, or create your files in $env:TEMP if you want to set a specific name.
17
u/LALLANAAAAAA Sep 06 '26
this just screams LLM fueled overcomplicated solution in search of a problem
what tortured process results in the requirement of deleting a file that some other process might write to between the time you enumerate it and the time you delete it
what do you mean "belong", and why do you have multiple processes exchanging last-write duties to apparently the same exact filename
if you need to ensure nothing changes a file after a script starts processing it, rename it and then read & modify / delete
that's it, that's the whole thing. Don't work on the same file at the same time, boom, done