Home > Blockchain >  What's the easiest way to recursively zip files within a directory that starts with the same na
What's the easiest way to recursively zip files within a directory that starts with the same na

Time:11-15

I have a directory (2022) that has subdirectories with a date as their name (20220101, 20220102, etc).

In each subdirectory I have files that I want to archive. These files have a name that starts with either L0283 or L0284 and then numbers and dates afterwards. E.g.: L0284408.20220101.2123. The filter I want to use is L028*. I want to archive each file in the same folder that they currently live in with a zipped a folder named 400401_L0283408archive.zip or 400401_L0284408archive.zip, depending on whether it was a L0283 or L0284 file.

That archive already exists, I can write a script that deletes it first but if I can overwrite it then it would save some time. I'll be rerunning this script in multiple root directories.

I looked into powershell's Compress-Archive functionality but I couldn't figure out how to add a filter to the file name and have a different output name, plus the 0283 vs 0284 was eluding me.

Thanks in advanced!

CodePudding user response:

Do you have PKZip? This works:

pkzipc -add -recurse -path 400401_L0283408archive.zip 2022/L0283*
pkzipc -add -recurse -path 400401_L0284408archive.zip 2022/L0284*

Those find and archive files that match the pattern at any level in the subdirectories of 2022/.

CodePudding user response:

I prefer to use the System.IO.Compression library for flexibility. You can specify the relative path within the zip file, and keep the file open for efficient writing if you prefer. However, based on your requirements it seems there will be multiple zip files (one per child folder), so I'd recommend closing the zip with Dispose() after each write. Here's an untested and inefficient example that will do what you say:

@( 'System.IO.Compression','System.IO.Compression.FileSystem') | % { [void][Reflection.Assembly]::LoadWithPartialName($_) }
Set-Location '.\2022'
$FilesToZip = Get-ChildItem 'L0283*' -File -Recurse 
ForEach($file in $FilesToZip){
    Try{
        Set-Location $file.Directory.FullName #change to the folder where the file exists
        $WriteArchive = [IO.Compression.ZipFile]::Open( '.\400401_L0283408archive.zip', 'Update')#Update mode adds files to new or existing zip
        [IO.Compression.ZipFileExtensions]::CreateEntryFromFile($WriteArchive, $file.FullName, $file.Name, 'Optimal')
    }Finally{
        $WriteArchive.Dispose() #close the zip file so it can be read later     
    } 
}


$FilesToZip = Get-ChildItem 'L0284*' -File -Recurse 
ForEach($file in $FilesToZip){
    Try{
        Set-Location $file.Directory.FullName #change to the folder where the file exists
        $WriteArchive = [IO.Compression.ZipFile]::Open( '.\400401_L0284408archive.zip', 'Update')#Update mode adds files to new or existing zip
        [IO.Compression.ZipFileExtensions]::CreateEntryFromFile($WriteArchive, $file.FullName, $file.Name, 'Optimal')
    }Finally{
        $WriteArchive.Dispose() #close the zip file so it can be read later     
    } 
}

It's inefficient because it opens and closes the archive with each write. I repeated code for simplicity, but if I had control over the zip file structure I would rewrite this script to create a single zip containing all the files while preserving the relative path, like I mentioned in this answer.

  • Related