How to zip / archive hidden files using Compress-Archive?

I've just had the same issue and this is how I got aroung it

# WARNING: This only works on a windows based powershell core terminal instance.
# In a linux based powershell core instance the .dot files are not included in 
# the final archive when using the -Filter example

# This will include .files like .gitignore
Get-ChildItem -Path . -Filter *.* | Compress-Archive -DestinationPath dist.zip

# This will include .dot files like .gitignore and any that are hidden like .git
Get-ChildItem -Path . -Force | Compress-Archive -DestinationPath dist.zip

This looks like a bug/oversight in the Compress-Archive cmdlet. Since the cmdlet provides no "include hidden files" parameter but does accept a collection of source files via the -Path or -LiteralPath parameters, I would expect either this...

Compress-Archive -Path (
    Get-ChildItem -Path '...' -Force `
        | Select-Object -ExpandProperty 'FullName' `
) -DestinationPath '...'

...or this...

Get-ChildItem -Path '...' -Force | Compress-Archive -DestinationPath '...'

...to work as a way of passing hidden files to the cmdlet; the key being specifying the -Force parameter for Get-ChildItem. Both of those invocations, however, throw these errors...

Get-Item : Could not find item ....
At C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:814 char:63
+ ... Entry.LastWriteTime = (Get-Item -LiteralPath $currentFilePath).LastWr ...
+                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (...:String) [Get-Item], IOException
    + FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetItemCommand

Exception setting "LastWriteTime": "Cannot convert null to type "System.DateTimeOffset"."
At C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Microsoft.PowerShell.Archive\Microsoft.PowerShell.Archive.psm1:814 char:25
+ ...             $currentArchiveEntry.LastWriteTime = (Get-Item -LiteralPa ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
    + FullyQualifiedErrorId : ExceptionWhenSetting

...for the first hidden file in the input list. (Note that invoking the first snippet without Select-Object -ExpandProperty 'FullName' instead throws Compress-Archive : The path '...' either does not exist or is not a valid file system path..)

On my system, the referenced lines 812-814 of Microsoft.PowerShell.Archive.psm1 are...

# Updating  the File Creation time so that the same timestamp would be retained after expanding the compressed file. 
# At this point we are sure that Get-ChildItem would succeed.
$currentArchiveEntry.LastWriteTime = (Get-Item -LiteralPath $currentFilePath).LastWriteTime

So, even if we pass -Force to Get-ChildItem to get the paths of hidden file objects to pass to Compress-Archive, internally the cmdlet is fetching those file objects again using Get-Item...but it's not passing -Force, which of course will fail (despite what the comment on the previous line claims). Thus, I don't think there's any way to get Compress-Archive to work with hidden files without either you or Microsoft editing that script.


Well ...that's really annoying then! I've taken to using 7-Zip via Powershell but of course that does mean I'm using yet another tool. It also means it's almost redundant using Compress-Archive.

Here's part of my script delcaring the 7Zip variables and zipping stuff:

    $7ZipPath = "$env:ProgramFiles\7-Zip\7z.exe"
    
    If (-Not (Test-Path -Path $7ZipPath -PathType Leaf)) {
        throw "7 Zip File '$7ZipPath' Not Found"
    PAUSE
    }
    
    Set-Alias 7Zip $7ZipPath 
    
    $ItemsToZip = @{
    Path= "$TempDirectory\*"
    CompressionLevel = "Fastest"
    DestinationPath = $MyZipFile
    
    Compress-Archive @ItemsToZip
    
    7zip u $MyZipFile -ux2y2z2 "C:\Path\HiddenFile.ext"

Hope that helps someone


I replaced Compress-Archive with \[System.IO.Compression.ZipFile]::CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName) and found (on macOS at least) that the ZIP-file included a directory that starts with . (which is one way to hide a directory/file on macOS). This is using PowerShell 7.2.