3

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
  • 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 '18 at 14:46
  • @AFH these parameters seem to apply for wim and tar formats only – kamikatze13 Oct 26 '18 at 14:53
1

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

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

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

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

OR

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 – kamikatze13 Oct 19 '20 at 17:45
4

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\ -xr@exclude.txt
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 -xr@exclude.txt 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.