0

Folder X has a lot of subfolders A,B,C,D... each subfolder has a lot of files and I want to archive all files that are in those subfolders and that are older than 6 months. After that check if archive is created and delete the files that have been archived.

Here is what I tried:

#$SourceFolder = "C:\Users\sec\Desktop\X"

ForEach-Object 
{
    Get-ChildItem -Path "$($_.FullName)" -Exclude "*.zip"
    Where-Object {($_.LastWriteTime -lt (Get-Date).AddMonths(-6))} |
        Compress-Archive -DestinationPath "$($_.FullName)\06.2020andOlder.zip" -Update;

    if (Test-Path 06.2020andOlder.zip) {
        Remove-Item -Force
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • Should each subfolder have its own `06.2020andOlder.zip` archive or do you want to store everything in one larger zip file? – Theo Dec 27 '21 at 11:52
  • Each folder should have its own zip because in each folder I have logs for different machines and in case I want to look for them someday it will be easier to find. –  Dec 27 '21 at 12:13
  • That's what i assumed, but it wasn't too clear. PLease see my answer to do this below. – Theo Dec 27 '21 at 12:17
  • If you store each file's relative path, it's still pretty easy to find and leaves you with fewer zip files and slightly better compression. Try my solution [here](https://stackoverflow.com/questions/53740869/how-to-compress-log-files-older-than-30-days-in-windows/53752330#53752330) and see if it suits your needs. – Rich Moss Jan 05 '22 at 20:51

1 Answers1

1

Assuming you want each subfolder to end up with a .zip archive where the older files are in, try this:

Use Group-Object to group all older files within the same subdirectory together and use that to the create the .zip file and also to remove the original files after zipping.

$SourceFolder = 'D:\Test'
$refDate      = (Get-Date).AddMonths(-6).Date  # take this from midnight

Get-ChildItem -Path $SourceFolder -File -Recurse -Exclude "*.zip" | 
    Where-Object { $_.LastWriteTime -lt $refDate } |
    Group-Object DirectoryName | ForEach-Object {
        # construct the target folder path for the zip file using the Name of each group
        $zip = Join-Path -Path $_.Name -ChildPath '06.2020andOlder.zip'
        # archive all files in the group
        Compress-Archive -Path $_.Group.FullName -DestinationPath $zip -Update

        # here is where you can delete the original files after zipping
        $_.Group | Remove-Item -WhatIf
    }

Note I have added switch -WhatIf to the Remove-Item cmdlet. This is a safety switch, so you are not actually deleting anything yet. The cmdlet now only displays what would be deleted. Once you are happy with this output, remove that -WhatIf switch so the files are deleted.

Theo
  • 57,719
  • 8
  • 24
  • 41
  • Work's very well. Thank's a lot Theo!! –  Dec 27 '21 at 12:20
  • Theo, Is possbile to create an archive with everything you find in the folder, it doesn't matter if it's a file or a folder? (in this moment if in Folder 'A' find another folder 'A1' the script create 1 zip in A and 1 zip in A1 ; create only 1 archive in folder 'A' and include folder A1. –  Dec 27 '21 at 12:50
  • 1
    @Bogdan I wouldn't try that because [1] at what level of subdirs would you like it to start collecting ? [2] you would risk file naming collisions in the zip file meaning a file from subfolder `A1\A2\A624` could overwrite the files with the same name from parent directories. – Theo Dec 27 '21 at 13:47
  • @Theo Naming collisions are minimized if you store the files with their relative paths. `Compress-Archive` does not easily support this, but `System.IO.Compression.FileSystem` API does. @Bogdan you can store the folder structure associated with a file, but empty folders aren't stored in a zip. – Rich Moss Jan 06 '22 at 16:51