On Windows, when using the commons-io@2.9
class FileUtils
to copy a directory (e.g. FileUtils.copyDirectory(...)
, the behavior differs from that of Windows default copy behavior, quoting (microsoft.com):
"By default, an object inherits permissions from its parent object, either at the time of creation or when it is copied or moved to its parent folder. The only exception to this rule occurs when you move an object to a different folder on the same volume. In this case, the original permissions are retained."
Expected behavior:
- Files copied to destination inherit parent permissions
Actual behavior:
- Files copied to destination do NOT inherit parent permissions
The reason this is important is that Windows historically manages these; setting them manually would be prone to even more potential errors. Thus, without the ability to inherit target permissions, this method does not serve the most common-use purpose on Windows.
How do I restore the old behavior of inheriting the target permissions without downgrading the commons-io
library?
This seems to be a regression in behavior:
Version | Status |
---|---|
commons-io@1.1 (2005) |
✅ Inherits permissions of destination |
commons-io@2.4 (2013) |
✅ Inherits permissions of destination |
commons-io@2.5 (2016) |
✅ Inherits permissions of destination |
commons-io@2.6 (2017) |
✅ Inherits permissions of destination |
commons-io@2.7 (2020) |
✅ Inherits permissions of destination |
commons-io@2.8 (2020) |
✅ Inherits permissions of destination |
commons-io@2.9 (2021) |
Does not inherit permissions of destination |
commons-io@2.10 (2021) |
Does not inherit permissions of destination |
commons-io@2.11 (2021) |
Does not inherit permissions of destination |
For example, if copying to C:\Program Files
Version | Permissions (icals <file> ) |
---|---|
commons-io@2.8 |
NT AUTHORITY\SYSTEM:(I)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Users:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX) |
commons-io@2.9 |
NT AUTHORITY\SYSTEM:(F) BUILTIN\Administrators:(F) WIN10ARM\owner:(F) |
Sample code:
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
public class Main {
private static final String PROGRAM_FILES = System.getenv().get("ProgramFiles");
public static void main(String ... args) throws IOException {
// Prepare our folder
File folder = new File("MyApp");
folder.mkdirs();
File file = new File(folder, "test.txt");
file.createNewFile();
// Use FileUtils to copy it elsewhere
File parent = new File(PROGRAM_FILES);
File dest = new File(parent, "MyApp");
System.out.println(String.format("Creating parent folder %s...", dest));
dest.mkdirs();
System.out.println(String.format("Copying contents %s to %s...", folder, dest));
FileUtils.copyDirectory(folder, dest);
// To test permissions call:
// icacls "%ProgramFiles%\MyApp\test.txt"
}
}
To compile the code:
javac -cp lib\commons-io-2.8.jar src\Main.java
To run the code (open a CMD as administrator):
java -cp lib/commons-io-2.8.jar;src Main
To test permissions:
icacls "%ProgramFiles%\MyApp\test.txt"
Then manually delete %ProgramFiles%\MyApp
and repeat for commons-io-2.9.0.jar
.
Similar questions have been asked before, but I could not find an explanation for this behavior.
Apache commons-io
Mailing list discussion:
Related:
- How to preserve file permissions when using FileUtils.copyDirectory?
- Java File copy - how to inherit permissions of destination directory
A possible workaround, but much more complex: