PS > $p = "$env:TEMP\$([System.Guid]::NewGuid().ToString('n'))"
PS > md $p | cd
PS > md dir1; cd dir1;
PS > '1' | sc file1
PS > cd ..
PS > Compress-Archive . zipped.zip
PS > explorer .
zipped.zip to a Mac with OS X El Capitan 10.11.3;zipped.zip and decompress it with Archiver (if the Mac is brand-new, double-clicking the file should work).The decompression gives a folder <the guid generated>, in which there is a folder dir1, in which there is a file file1.
The decompression gives a file <the guid generated>\dir1\file1.
> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.14393.82
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.14393.82
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Please identify if this is a problem with Compress-Archive cmdlet or OS X Archiver. If this is a problem with Compress-Archive, please fix the cmdlet in the next version. If this is a problem with OS X Archiver, please notify me so that I can forward the issue to Apple.
Also, I cannot test Compress-Archive in PowerShell Core or Expand-Archive in PowerShell Core at this time. If someone would like to test this, please do not hesitate to report it here.
Thank you for pointing it out!
I verified the problem.
I actually seen this problem before, with unpacking our AppVeyor artifacts on OS X.
I researched the problem a little bit and here is what I found
[System.IO.Compression.ZipFile]::CreateFromDirectory provides the same incompatible archive (that's what we use in our AppVeyor artifacts packaing)[System.IO.Compression.ZipFile]::CreateFromDirectory creates a good, compatible archiveCreateEntry in System.IO.Compression.ZipArchive class inside Compress-Archive. We may use it incorrectly or there could be a problem in corefx. Need more investigations here.https://github.com/PowerShell/Microsoft.PowerShell.Archive/issues/11
We should track Archive issues in its own repo. The Archive module in PowerShell/PowerShell will be a submodule: https://github.com/PowerShell/PowerShell/issues/1979
We got a similar bug report in the dotnet/corefx repo, and the issue seems to only happen with files generated using PowerShell's Compress-Archive cmdlet, (no other compression tools show this problem): https://github.com/dotnet/corefx/issues/32788
When using PowerShell in Windows to create a zip file, it cannot be extracted in Linux/Unix using .NET Core libraries because of the directory separator enforced by PowerShell.
PowerShell should either use the libraries offered for .NET Core to generate zip files (which ensure the correct directory separator is always used independently of the OS) or modify their existing code (which inserts each zip file entry individually to the zip file) to ensure the paths of the zip files use the universally accepted directory separator "/".
Note: There used to be a bug on our side (as pointed out by @vors) but it has already been fixed both in .NET Core and in .NET Framework.
Can repro both in the latest version of PowerShell and in 1.0 (the one included with Windows 10).
PS D:\source\repos> New-Item -Type Directory -Path Folder
PS D:\source\repos> New-Item -Type Directory -Path Folder\SubFolder
PS D:\source\repos> echo "Hello world" > Folder\SubFolder\file.txt
PS D:\source\repos> Compress-Archive Folder compressed.zip
The ZipFileExtensions.ExtractToDirectory function avoids making assumptions about separators, in case the user is interacting with a zip file that does not contain files and folders, but something else. But if the zip file happens to contain files and folders, the character used as separator in Linux should always be "/".
But because PowerShell inserted each one of the zip archive entries into the zip file manually, the directory separator used was "", which is only valid in Windows. When attempting to extract this file in Linux/Unix using .NET Core, it's not possible because the file has invalid characters that prevent ensuring the correct creation of its subfolders.
There are two places in the PowerShell code that could be modified to ensure the universally accepted directory separator is used:
if($null -ne $currentFileStream)
{
$srcStream = New-Object System.IO.BinaryReader $currentFileStream
$entryPath = DirectorySeparatorNormalizeHelper $relativeFilePath
$currentArchiveEntry = $zipArchive.CreateEntry($entryPath, $compression)
else
{
$entryPath = DirectorySeparatorNormalizeHelper $relativeFilePath
$currentArchiveEntry = $zipArchive.CreateEntry($entryPath, $compression)
$numberOfItemsArchived += 1
$addItemtoArchiveFileMessage = ($LocalizedData.AddItemtoArchiveFile -f $currentFilePath)
}
In both places, the lines that generate the $entryPath string should instead be:
$entryPath = DirectorySeparatorNormalizeHelper $relativeFilePath.Replace("\", "/")
Alternatively, PowerShell could be initialized with the ZipArchiveEntry.FullName Path Separator AppContextSwitchOverride turned off: https://docs.microsoft.com/en-us/dotnet/framework/migration-guide/mitigation-ziparchiveentry-fullname-path-separator
Please let me know if we can reopen this bug or if I should create a new one.
I just stumbled upon the same issue on Linux when opening an Zip-File that I created with Compress-Archive on a Win10 host. After uncompressing such Archives on Linux, nested subfolders and files will appear with concatenated names such as "folder\subfolder\test.txt", all cluttered in the root folder.
Mentioning @SteveL-MSFT in case the comments get buried.
Edit: My bad, I added a space after the @ character.
@SteveL-MSFT since Github apparently decided to eat that mention 馃し鈥嶁檪
The fix was merged. @anmenaga will publish a version to PSGallery by next week.
Yay! Thank you! 馃帀
Great - thanks a lot!
Most helpful comment
I just stumbled upon the same issue on Linux when opening an Zip-File that I created with Compress-Archive on a Win10 host. After uncompressing such Archives on Linux, nested subfolders and files will appear with concatenated names such as "folder\subfolder\test.txt", all cluttered in the root folder.