5

Windows 1803, 7z 18.05

Trying to archive and compress a folder structure with multiple NTFS junctions referencing parts of the said structure (i.e. no "outside" links) - any possibility to compress the structure without 7zip resolving the junctions, resulting in duplicates?

Preserving the junctions would be neat, archiving the junctions as empty folders would also be acceptable - but archive size has absolute priority.

Choosing tar or wim as format has options about NTFS symlinks, but doesn't seem to involve compression (only store is presented as compression level) - I'd have to compress afterwards, which seems an unnecessary intermediate step.

I could delete the junctions before archiving, but I'd rather not to, if possible.

2
  • 1
    The 7z.exe command-line interface has the options: -snh : store hard links as links and -snl : store symbolic links as links, but I can't see any options for these in the GUI version, either in Options or in the archive creation dialogue.
    – AFH
    Oct 26, 2018 at 14:46
  • @AFH these parameters seem to apply for wim and tar formats only Oct 26, 2018 at 14:53

4 Answers 4

2

it's obvious 7z (using 20.02 alpha) is not capable of preserving junctions. no solutions provided on the web work. creating a WIM archive thru 7z will seemingly preserve junctions, but unpacking the archive later on will break them, verify yourself using Russinovich's junction programme:

junction "D:\linux\shared\Work\www"

D:\linux\shared\Work\www: JUNCTION

Substitute Name: c:\program files\internet\proxydomo\html

Now, compressing folder "D:\linux\shared" to WIM (same applies to TAR) archive in 7z, then unpacking it, will break the junction, pointing it to:

D:\linux\shared\Work\www: JUNCTION

Print Name : D:\linux\shared\program files\internet\proxydomo\html

Substitute Name: D:\linux\shared\program files\internet\proxydomo\html

Solution? Use dism instead:

https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism-image-management-command-line-options-s14

create an image:

dism /Capture-Image /ImageFile:D:\Copy\shared.wim /CaptureDir:D:\linux\shared /Name:shared /Compress:fast /Verify

mount the image into an empty directory and unmount it (and disrcard all changes - alternative would be /commit that updates the image):

dism /mount-image /imagefile:shared.wim /index:1 /mountdir:D:\Copy\Fix\test

dism /unmount-image /mountdir:D:\Copy\Fix\test\ /discard

or extract the image content to an empty directory:

dism /Apply-Image /ImageFile:shared.wim /Index:1 /ApplyDir:D:\Copy\Fix\test /Verify

junctions are preserved properly. Relying on 3rd party programmes simply cannot achieve positive results. Logic dictates this. The Creator knows its own system best. What is true for God applies to everything and everybody else as well.

1
  • finally had time to try it out and this is, imho, the best approach so far for the problem at hand, until 7zip natively supports preservation of ntfs junctions Oct 19, 2020 at 17:45
7

I would suggest to go in two steps :

  1. Generate a list of all the junctions in the folder
  2. Create a 7Zip archive from the folder while excluding the files in the list.

For the first step, you may use the following command in a Command Prompt :

dir /AL /S /B your-folder > exclude.txt

Where :

  • /A displays all files with a specific attribute, and L specifies reparse points (symlinks and directory junctions)
  • /S makes the command recursive
  • /B specifies the bare format of only file names.

When zipping the folder use the -x (Exclude filenames) switch :

7z a archive.7z folder\ [email protected]
0

Complementing @harrymc answer, and responding to your need of "Preserving the junctions would be neat, archiving the junctions as empty folders would also be acceptable - but archive size has absolute priority." you could store your junctions as plain text files, and then 7zip with the [email protected] as suggested by @harrymc. This way you have both requirements covered, at the expense of creating a "fake" .junction file in the same destination of your junction.

You would need to recursively follow all junctions and for each one, extract the substitution name and save it into a file

for /d /r %%a in (%1\*) do if exist %%a\nul call :storejunction "%%~dpnxa"
goto :eof

:storejunction
set attribs=%~a1
if not "%attribs:~-1%" == "l" goto :eof
for /f "tokens=3*" %%b in ('junction %~s1 ^| find "Substitute Name:"') do set "jname=%%b"
echo %jname% >"%~f1.junction"
goto :eof
0

Adding on to @harrymc 's answer. When I ran the dir command, all my paths were output as an absolute path. Supposedly, the 7z -x command is expecting relative paths and I was not able to get it to obey the exclusion list at first. Adding -spf option to 7z tells it to expect absolute paths and it worked as expected after this.

7z a archive.7z folder\ -spf [email protected]

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .