Powershell for archiving old data

I'd like to delete old files of a certain age and leave a shortcut saying this file has been archived using Powershell.

I'd like to delete old files of a certain age and leave a shortcut saying this file has been archived using Powershell

You have to ask a specific question about Powershell code you wrote. Id would be helpful as well when you post the code you already have and explain what’s not working as expected.

This is what I have so far, but I’d like to add a shortcut for each file that is deleted with the name of the file.ARCHIVED

 

Delete all Files in C:\temp older than 30 day(s)

$Path = “C:\temp”
$Daysback = “-30”

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
Get-ChildItem $Path -Recurse ( | Where-Object { $_.LastWriteTime -lt $DatetoDelete } | Remove-Item

Correct me if I’m wrong but you’re not archiving the files - you’re deleting them. Instead of the Remove-Item you could use a Foreach-Object loop, copy the files to a location of your choice and with the New-Item cmdlet with the parameter -ItemType eihter with SymbolicLink, Junction or HardLink you can create the shortcut.

Regardless of that - when you post code please format it as code using the code tag button (pre) of the icon bar of the post editor.

Apologies for not using the code tag. Let me try explain what I’m trying to achieve as I’m fairly new to Powershell.

We have a file server with several gigabytes of old data within various folders. We don’t have to move the files to another location as we’ll be creating a backup for the file server so we can restore the data should we need to at a later date.

 

What we want to do is rename the file being deleted with a marker with its original_ARCHIVED. We know the files aren’t being archived but rather deleted, so our users will assume the files were archived.

If you know a way of doing this, please can you post the code I’d really appreciate it. Thanks

Ah … ok … that’s even easier. Instead of creating a working shortcut you just use the original file name and create an empty file with the specified name change … like this:

$Path = “C:\temp”
$Daysback = “-30”

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
Get-ChildItem -Path Path -Recurse | Where-Object { .LastWriteTime -lt DatetoDelete } | ForEach-Object { Remove-Item -Path .FullName
NewName = Join-Path -Path .Directory -ChildPath (_.BaseName + '_archived' + .Extension)
New-Item -Path $NewName -ItemType File
}

Thanks so much for your assistance with this script, I’ll be testing it this evening when I can arrange an outage. One more query, if I wanted to date stamp the name of the file after _archived. Would that be possible?

Yes. Definitely. :wink:

Would you mind updating your script to include this please? I’d really appreciate it. Thanks

Actually yes. I’m sure you will be able to figure that out by yourself really fast. Just try to analize what the code does and google how to do a time stamp in Powershell and you will become a Powershell hero really quickly. :wink:
Good luck and have a lot of fun.

Will try and workout how I do this over the weekend. Really appreciate all your help with this query. Thanks

Finally cracked it, thought I’d share my code with you. Would you have done it another way?

$Path = "C:\temp"
$Daysback = "-30"

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)
$time = get-date -format dd-MM-yyyy

Get-ChildItem -Path $Path -Recurse  | 
    Where-Object { $_.LastWriteTime -lt $DatetoDelete } | 
        ForEach-Object {
            Remove-Item -Path $_.FullName
            $NewName = Join-Path -Path $_.Directory -ChildPath ($_.BaseName + '_archived_' + $time + $_.Extension)
            New-Item -Path $NewName -ItemType File
        }

Great. I’m proud of you. And thanks for sharing.

To simplify your code a tiny bit … you already have a DateTime in a variable … you can use this:

$Path = “C:\temp”
$Daysback = “-30”

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)

Get-ChildItem -Path Path -Recurse | Where-Object { .LastWriteTime -lt DatetoDelete } | ForEach-Object { Remove-Item -Path .FullName
NewName = Join-Path -Path .Directory -ChildPath (_.BaseName + '_archived_' + (CurrentDate.ToString('dd-MM-yyyy')) + .Extension)
New-Item -Path $NewName -ItemType File
}

Thanks for the feedback, I’ll definitely keep practising and hopefully manage to master Powershell in the future.

 

Just incase I want to run this script on other servers which have multiple drives (C: E: F:) can I add these to the $Path or would you suggest another way?

There are a lot of improvements thinkable. You could it simply wrap it in a loop iterating over the drives one after the other. Or you could run it in parallel to increase the speed… Or you could provide the drive you like to treat as a parameter to decide case by case what drive to treat … :wink:

Would you recommend I search multiple drives (C,E,F) like this or should I use get-psdrive -p "FileSystem ?

$Path = "C:\","E:\","F:\"
$Daysback = "-30"

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)

Get-ChildItem -Path $Path -Recurse  | 
    Where-Object { $_.LastWriteTime -lt $DatetoDelete } | 
        ForEach-Object {
            Remove-Item -Path $_.FullName
            $NewName = Join-Path -Path $_.Directory -ChildPath ($_.BaseName + '_archived_' + $($CurrentDate.ToString('dd-MM-yyyy')) + $_.Extension)
            New-Item -Path $NewName -ItemType File
        }

That depends pretty much on what you expect your script to do. If you’re sure about to treat always really all local drives you can give it go with Get-PSDrive. If you like to control what local drives to treat you should provide the drive letters explicitly.

Hi There,

With my script above is there a way I can pipe the files that change into a CSV?

Thanks

 

Sure … why not? You have the FullName of the file you want to change and you have the $NewName. A good way could be to collect the information you’re after in a [PSCustomObject] inside the loop and output it at the end.

I’ve changed my script to this but unfortunately it’s not outputting to a CSV. Could you possible confirm where I’ve gone wrong? Thanks

$Path = "F:\","G:\","H:\"
$Daysback = "-30"
$filesRenamed = ""


 

$CurrentDate = Get-Date
$DatetoDelete = $CurrentDate.AddDays($Daysback)

 


Get-ChildItem -Path $Path -Recurse -Attributes !Directory+!System  | 
    Where-Object { $_.LastWriteTime -lt $DatetoDelete `
        -and $_.FullName -notlike "F:\Snap Server\*" `
        -and $_.FullName -notlike "H:\Apps\*" } |
        ForEach-Object {
            $filesRenamed = $filesRenamed + "," + $_.FullName
            Remove-Item -Path $_.FullName
            $NewName = Join-Path -Path $_.Directory -ChildPath ($_.BaseName + '_archived_' + $($CurrentDate.ToString('dd-MM-yyyy')) + $_.Extension)
            New-Item -Path $NewName -ItemType File
        }
        $filesRenamed.TrimStart(",")

 

        write-host "Files that have been renamed: " + $filesRenamed >> C:\Scripts\RenamedFiles.csv