1

I need to include empty directories along with files in a zip file. I can do this manually just fine with 7-Zip but I wanted to automate it because I do this quite a lot. I recently started learning powershell so I decided to give it a go.

My problem is that Compress-Archive automatically discards empty directories. My workaround is ($Files is a parameter to the script):

$items = Get-ChildItem -Path . | Where-Object { $_.Name -in $Files }
$placeholders = @()
foreach ($item in $items) {
    if (($item | Get-ChildItem | Measure-Object).Count -eq 0 ) {
        $placeholders += (New-Item -Path "$item\.placeholder")
    }
}

and at the end of the script

foreach ($item in $placeholders) {
    $item.Delete() 
}

which works but it is not pretty as it results in placeholder files being in the final zip.

Is there a good way to compress empty directories in powershell?

EDIT whole script with version info at the bottom:

[CmdletBinding()]
param (
    # Files and folders to compress, comma separated
    [Parameter(Mandatory)]
    [string[]]
    $Files,

    # zip file to create
    [Parameter(Mandatory)]
    [string]
    $ZipName
)

if (-not $ZipName.Contains(".zip")) {
    $ZipName += ".zip"
}

$items = Get-ChildItem -Path . | Where-Object { $_.Name -in $Files }
$placeholders = @()
foreach ($item in $items) {
    if (($item | Get-ChildItem | Measure-Object).Count -eq 0 ) {
        $placeholders += (New-Item -Path "$item\.placeholder")
    }
}

if ((Get-ChildItem -Path . | Where-Object { $_.Name -eq $ZipName } | Measure-Object).Count -ne 0) {
    Remove-Item -Path "$ZipName"
}

$items | Compress-Archive -DestinationPath $ZipName

foreach ($item in $placeholders) {
    $item.Delete() 
}

# output of Get-Host
# Name             : ConsoleHost
# Version          : 5.1.19041.610
# InstanceId       : c799930e-ea5e-4ec9-9e5d-41d949bf4ee4
# UI               : System.Management.Automation.Internal.Host.InternalHostUserInterface
# CurrentCulture   : en-GB
# CurrentUICulture : en-GB
# PrivateData      : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
# DebuggerEnabled  : True
# IsRunspacePushed : False
# Runspace         : System.Management.Automation.Runspaces.LocalRunspace

EDIT2 very weird stuff. Tested it again and I swear it does not work for me. If I give it the names of empty directories it doesn't even create a zip file. I'm going to reinstall Windows as soon as my new ssd arrives, maybe that fixes it.

By the way I needed this for Wordpress plugin development as you have to upload the plugins in a zip file. I uploaded the archive I created with this script and it produced a very weird result. Instead of correctly uncompressing the zip as Wordpress has done every single time before what it did was something like this:

some\file\which\should\be\in\a\directory.php
weird\file\again.php
normal.php

No, those are not paths, they are filenames. On Windows I can uncompress it just fine. I am so confused.

  • I cannot duplicate. Empty directories are included in the zip file. What version of PS are you using? Probably best to show your Compress-Archive command. – Doug Maurer Mar 18 '21 at 21:16
  • @DougMaurer I edited the question so the whole script and version info is there – strokeberry Mar 18 '21 at 21:34
  • By saying `| Where-Object { $_.Name -in $Files }` you're automatically filtering those folders without a "File" hence those empty folders are not being compressed. Unless, $Files actually contains Names of Folders you're looking for. – Santiago Squarzon Mar 18 '21 at 21:36
  • @santisq it does contain the names of the directories, see parameter description – strokeberry Mar 18 '21 at 21:43
  • Confirming that I have the same problem. Zipping empty folders in Powershell results in no file, and frustratingly no error returned. In my case, it means I need to check for existence of files before attempting to zip, otherwise subsequent actions with the zip file I thought I created will fail. – hazymat Mar 29 '23 at 08:46

1 Answers1

0

As Doug Maurer stated, there are no issues while compressing empty folders in PS. I also put your function into test and did not find any issues. I'm able to compress empty folders without any problem:

PS /home/zen/Documents/test> gci -Recurse ./emptyfolderIpromise/


    Directory: /home/zen/Documents/test/emptyfolderIpromise

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:53 PM                emptyfolderinsideemptyfolder

    Directory: /home/zen/Documents/test/emptyfolderIpromise/emptyfolderinsideemptyfolder

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:53 PM                insideemptyfolder

    Directory: /home/zen/Documents/test/emptyfolderIpromise/emptyfolderinsideemptyfolder/insideemptyfolder

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:53 PM                insideeeee

PS /home/zen/Documents/test> superCompresser -Files emptyfolderIpromise -ZipName myemptycompressedfolder

PS /home/zen/Documents/test> gi ./myemptycompressedfolder.zip                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Directory: /home/zen/Documents/test                                                                                                                                                                                                                                                                                                                                                                   
Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-----           3/18/2021  6:54 PM            638 myemptycompressedfolder.zip

PS /home/zen/Documents/test> remove-item ./emptyfolderIpromise/ -Recurse -Force

PS /home/zen/Documents/test> gi ./emptyfolderIpromise/                         

Get-Item: Cannot find path '/home/zen/Documents/test/emptyfolderIpromise/' because it does not exist.

PS /home/zen/Documents/test> Expand-Archive ./myemptycompressedfolder.zip

Recurse   ReadOnly  PS /home/zen/Documents/test> gci ./myemptycompressedfolder -Recurse                                                                                                                                  


    Directory: /home/zen/Documents/test/myemptycompressedfolder

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:56 PM                emptyfolderIpromise

    Directory: /home/zen/Documents/test/myemptycompressedfolder/emptyfolderIpromise

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:56 PM                emptyfolderinsideemptyfolder

    Directory: /home/zen/Documents/test/myemptycompressedfolder/emptyfolderIpromise/emptyfolderinsideemptyfolder

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:56 PM                insideemptyfolder

    Directory: /home/zen/Documents/test/myemptycompressedfolder/emptyfolderIpromise/emptyfolderinsideemptyfolder/insideemptyfolder

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----           3/18/2021  6:56 PM                insideeeee

PS /home/zen/Documents/test> 
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • I edited the post as it was too long for a comment, please check it out – strokeberry Mar 18 '21 at 22:53
  • Are you 110% sure that when you're running your function and passing the empty folder as parameter your current directory is where the empty folder is??? – Santiago Squarzon Mar 18 '21 at 23:09
  • In addition, if you can go to windows explorer > right click an empty folder > compress it and that works then the same can be done in powershell, im pretty sure this is not an issue with your OS. – Santiago Squarzon Mar 18 '21 at 23:10
  • Yes I am a 100% sure because if I uncomment the workaround the empty folders are included in the zip with the placeholder files. Oh wow I checked the built-in Windows archiver or whatever it's called and it does not work, even throws a warning that it's unable to put one or more files in. If I want to zip an empty folder only it won't let me, throws an error. Powershell should be cross-platform and behave the same or so I thought. I see it works well for you on linux, well it's not working on Windows, we'll see after the reinstall. – strokeberry Mar 18 '21 at 23:21
  • Ok, well. I actually tried on Windows and in fact I don't get any .zip after compressing an empty folder, I don't get any error either. I tried with `-Force`. So you were right and I was wrong. Now i'm not sure if this is a behavior of Windows or behavior of PS 5.1. – Santiago Squarzon Mar 18 '21 at 23:44