Toy example:
I created one directory with a symlink to it and a regular file with a symlink to it like so:
$ mkdir tmp
$ cd tmp
$ mkdir a; ln -s a b; touch c; ln -s c d
$ cd ..
$ tree tmp
tmp
├── a
├── b -> a
├── c
└── d -> c
Ideally what would happen is the following:
$ zip -yr tmp.zip tmp
$ unzip tmp.zip -d newtmp
Archive: tmp.zip
creating: newtmp/tmp/
creating: newtmp/tmp/a/
extracting: newtmp/tmp/c
linking: newtmp/tmp/d -> c
linking: newtmp/tmp/b -> a
finishing deferred symbolic links:
newtmp/tmp/d -> c
newtmp/tmp/b -> a
$ tree newtmp
newtmp
└── tmp
├── a
├── b -> a
├── c
└── d -> c
I then attempted to use Zip4j to zip these files.
First attempt is a naive approach. Just setSymbolicLinkAction to INCLUDE_LINK_ONLY:
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class ZipTest {
public static void main(String[] args) throws IOException {
try (ZipFile zipFile = new ZipFile("test.zip");
Stream<Path> paths = Files.walk(Paths.get("tmp"))) {
paths.forEach(path -> {
ZipParameters zp = new ZipParameters();
if ((!Files.isSymbolicLink(path)) && Files.isDirectory(path)) {
zp.setFileNameInZip(path + "/");
} else {
zp.setFileNameInZip(path.toString());
}
zp.setSymbolicLinkAction(ZipParameters.SymbolicLinkAction.INCLUDE_LINK_ONLY);
try {
zipFile.addFile(path.toFile(), zp);
} catch (ZipException e) {
throw new RuntimeException(e);
}
});
}
}
}
Let's see what it contains:
$ unzip test.zip -d test && tree test
Archive: test.zip
creating: test/tmp/
creating: test/tmp/a/
extracting: test/tmp/c
linking: test/tmp/d -> c
extracting: test/tmp/b
finishing deferred symbolic links:
test/tmp/d -> c
test
└── tmp
├── a
├── b
├── c
└── d -> c
2 directories, 3 files
That didn't work. The symlink b to directory a, did not stay a symlink.
Then I tried only setting INCLUDE_LINK_ONLY for paths tested to be symlinks, and manually set CompressionLevel.NO_COMPRESSION and CompressionMethod.STORE.
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class ZipTest {
public static void main(String[] args) throws IOException {
try (ZipFile zipFile = new ZipFile("test.zip");
Stream<Path> paths = Files.walk(Paths.get("tmp"))) {
paths.forEach(path -> {
ZipParameters zp = new ZipParameters();
if ((!Files.isSymbolicLink(path)) && Files.isDirectory(path)) {
zp.setFileNameInZip(path + "/");
} else {
zp.setFileNameInZip(path.toString());
}
if (Files.isSymbolicLink(path)) {
zp.setSymbolicLinkAction(ZipParameters.SymbolicLinkAction.INCLUDE_LINK_ONLY);
zp.setCompressionLevel(CompressionLevel.NO_COMPRESSION);
zp.setCompressionMethod(CompressionMethod.STORE);
}
try {
zipFile.addFile(path.toFile(), zp);
} catch (ZipException e) {
throw new RuntimeException(e);
}
});
}
}
}
Unzipping output:
$ unzip test.zip -d test
Archive: test.zip
creating: test/tmp/
creating: test/tmp/a/
extracting: test/tmp/c
linking: test/tmp/d -> c
extracting: test/tmp/b
finishing deferred symbolic links:
test/tmp/d -> c
It still won't link b to a!
Toy example:
I created one directory with a symlink to it and a regular file with a symlink to it like so:
Ideally what would happen is the following:
I then attempted to use Zip4j to zip these files.
First attempt is a naive approach. Just
setSymbolicLinkActiontoINCLUDE_LINK_ONLY:Let's see what it contains:
That didn't work. The symlink
bto directorya, did not stay a symlink.Then I tried only setting
INCLUDE_LINK_ONLYfor paths tested to be symlinks, and manually setCompressionLevel.NO_COMPRESSIONandCompressionMethod.STORE.Unzipping output:
It still won't link
btoa!