Microsoft.PowerShell.Archive
Microsoft.PowerShell.Archive copied to clipboard
Compress-Archive creates a strange directory entry for certain file system configurations
Prerequisites
- [X] Write a descriptive title.
- [X] Make sure you are able to repro it on the latest released version
- [X] Search the existing issues.
- [X] Refer to the FAQ.
- [X] Refer to Differences between Windows PowerShell 5.1 and PowerShell.
Steps to reproduce
Sometimes, Compress-Archive
creates a weird directory-like entry in the produced archive. The details I was able to find:
- only in 2nd-level nested directory
- if said directory contains no files (i.e. is empty or only nested directories)
-
Compress-Archive
will create a ZIP entry called<yourDirectoryName>/
not marked as directory according to the output ofzipinfo
So, exact steps to reproduce:
$ md playground/pt/fspt/d
$ echo xxx >> playground/pt/fspt/d/file.txt
$ Compress-Archive playground/* -DestinationPath 'file.zip' -Force
Now, examine the resulting archive using zipinfo
(I wasn't able to quickly find a zipinfo
distribution for Windows, so installed sudo apt install unzip
on my Ubuntu into WSL):
$ zipinfo file.zip
Archive: file.zip
Zip file size: 233 bytes, number of entries: 2
-rw---- 2.0 fat 0 b- stor 22-Dec-07 20:56 pt/fspt/
-rw---- 2.0 fat 5 b- defN 22-Dec-07 20:56 pt/fspt/d/file.txt
2 files, 5 bytes uncompressed, 7 bytes compressed: -40.0%
The weird path is the first entry:
-rw---- 2.0 fat 0 b- stor 22-Dec-07 20:56 pt/fspt/
Notably, the weird entry goes away if I create a file in directory pt/fspt
:
$ echo 123 >> playground/pt/fspt/111.txt
$ Compress-Archive playground/* -DestinationPath 'file.zip' -force && wsl -d Ubuntu zipinfo file.zip
Archive: file.zip
Zip file size: 254 bytes, number of entries: 2
-rw---- 2.0 fat 5 b- defN 22-Dec-07 21:15 pt/fspt/111.txt
-rw---- 2.0 fat 5 b- defN 22-Dec-07 20:56 pt/fspt/d/file.txt
2 files, 10 bytes uncompressed, 14 bytes compressed: -40.0%
I've seen two kinds of other archives:
- The ones that contain no directory entries at all.
- The ones that contain directory entries with
drwxr-xr-x
flags instead of-rw----
.
At the same time, [System.IO.Compression.ZipFile]::CreateFromDirectory
works well:
$ [System.IO.Compression.ZipFile]::CreateFromDirectory($(Resolve-Path playground), "$(Resolve-Path '.')/file2.zip")
$ zipinfo file2.zip
Archive: file2.zip
Zip file size: 141 bytes, number of entries: 1
-rw---- 2.0 fat 5 b- defN 22-Dec-07 20:56 pt/fspt/d/file.txt
1 file, 5 bytes uncompressed, 7 bytes compressed: -40.0%
So, System.IO.Compression.ZipFile]::CreateFromDirectory
doesn't have this problem.
For empty directory, it will still create an entry with -rw----
flags, though, so it is not without problems.
Expected behavior
I'd say that Compress-Archive
should work the same way as System.IO.Compression.ZipFile]::CreateFromDirectory
.
Actual behavior
Compress-Archive
behaves differently from System.IO.Compression.ZipFile]::CreateFromDirectory
, and in a very strange way that is.
Environment data
The issue reproduces in both Windows PowerShell 5.1 and PowerShell 7.3.
# pwsh 7.3
Name Value
---- -----
PSVersion 7.3.0
PSEdition Core
GitCommitId 7.3.0
OS Microsoft Windows 10.0.22000
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
# powershell 5
Name Value
---- -----
PSVersion 5.1.22000.832
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.22000.832
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Zip listing strange but resulting zip-archive is correct.
It depends on your definition of "correct".
It depends on your definition of "correct".
Look at uzip. And unzipping as expected:
7z x file.zip
$ (dir ./pt -Recurse).FullName
/home/herz/Desktop/pt/fspt
/home/herz/Desktop/pt/fspt/d
/home/herz/Desktop/pt/fspt/d/file.txt
Perhaps this is a compression algorithm when empty directories are "merged" with a file.
If your definition of "correct" is "whatever 7zip works with", then yes, it is correct.
It is not correct w.r.t. every interop scenario, though.
In particular, java.util.zip.ZipEntry::isDirectory
has problems with such an archive: it reports directory entries to be files, which breaks things.
Though, after taking a closer look, I see that it only has problems with an archive created by Windows PowerShell 5.1, not PowerShell 7.3: it's the kind of the final slash that turns out to be important for it[^1]. Not the flags reported by zipinfo
.
The logic of creating directory entries only for directories of certain nesting level and with no files still looks kinda weird.
Notably, the version from the master
branch doesn't have this strange logic: it creates a new entry for every directory it seems.
[^1]: Not sure I mentioned that fact above, but the only notable difference between archives created by pwsh 5.1 and pwsh 7.3 is that 7.3 generated paths inside archives separated with /
(even on Windows), while pwsh 5.1 separates paths with \
.
If your definition of "correct" is "whatever 7zip works with", then yes, it is correct.
Yes. file-roller, unzip, 7-zip, mc and Far plugins. All of them extract file.zip without errors.I can't test the other archivers.