Skip to content

Commit 4f7d519

Browse files
Merge pull request #147 from mastodon-sc/fix-env-directory-size-unix
Improve directory size calculation on Unix
2 parents 12cbb56 + 26a02fa commit 4f7d519

1 file changed

Lines changed: 106 additions & 2 deletions

File tree

src/main/java/org/mastodon/mamut/util/appose/ApposeUtils.java

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,16 @@
44
import java.io.File;
55
import java.io.IOException;
66
import java.lang.invoke.MethodHandles;
7+
import java.nio.file.FileSystems;
8+
import java.nio.file.FileVisitResult;
79
import java.nio.file.Files;
10+
import java.nio.file.LinkOption;
11+
import java.nio.file.Path;
12+
import java.nio.file.SimpleFileVisitor;
13+
import java.nio.file.attribute.BasicFileAttributes;
14+
import java.util.Set;
815

16+
import javax.annotation.Nonnull;
917
import javax.swing.JOptionPane;
1018
import javax.swing.SwingUtilities;
1119

@@ -129,13 +137,109 @@ public static void deleteDirectory( final File dir ) throws IOException
129137
* @param directory The directory whose size is to be calculated. Must not be null and must represent a valid directory.
130138
* @return The total size of the directory in bytes. If the directory does not exist or is null, the method will return 0.
131139
*/
132-
public static long calculateDirectorySize( final File directory )
140+
public static long calculateDirectorySize( File directory )
141+
{
142+
if ( directory == null || !directory.exists() )
143+
{
144+
return 0;
145+
}
146+
147+
String os = System.getProperty( "os.name" ).toLowerCase();
148+
boolean isUnix = os.contains( "nix" ) || os.contains( "nux" ) || os.contains( "mac" );
149+
150+
if ( isUnix )
151+
{
152+
try
153+
{
154+
return calculateDiskUsageUnix( directory.toPath() );
155+
}
156+
catch ( IOException e )
157+
{
158+
// fallback to generic method if attribute not supported
159+
return calculateFileLengthRecursive( directory );
160+
}
161+
}
162+
else
163+
{
164+
return calculateFileLengthRecursive( directory );
165+
}
166+
}
167+
168+
// --- Linux/macOS: actual disk usage, like du -sb ---
169+
private static long calculateDiskUsageUnix( Path directory ) throws IOException
170+
{
171+
final long[] total = { 0 };
172+
boolean hasUnixView = supportsUnixAttributes();
173+
174+
Files.walkFileTree( directory, new SimpleFileVisitor< Path >()
175+
{
176+
@Nonnull
177+
@Override
178+
public FileVisitResult preVisitDirectory( @Nonnull Path dir, @Nonnull BasicFileAttributes attrs ) throws IOException
179+
{
180+
return Files.isSymbolicLink( dir )
181+
? FileVisitResult.SKIP_SUBTREE
182+
: FileVisitResult.CONTINUE;
183+
}
184+
185+
@Nonnull
186+
@Override
187+
public FileVisitResult visitFile( @Nonnull Path file, @Nonnull BasicFileAttributes attrs ) throws IOException
188+
{
189+
if ( !Files.isSymbolicLink( file ) )
190+
total[ 0 ] += getFileDiskUsage( file, hasUnixView );
191+
return FileVisitResult.CONTINUE;
192+
}
193+
} );
194+
195+
return total[ 0 ];
196+
}
197+
198+
private static boolean supportsUnixAttributes()
199+
{
200+
Set< String > views = FileSystems.getDefault().supportedFileAttributeViews();
201+
return views.contains( "unix" );
202+
}
203+
204+
/**
205+
* Returns the disk usage (in bytes) for a single file.
206+
* Uses actual allocated blocks if the unix view is supported.
207+
*/
208+
private static long getFileDiskUsage( Path file, boolean hasUnixView ) throws IOException
209+
{
210+
if ( !hasUnixView )
211+
return Files.size( file );
212+
213+
try
214+
{
215+
Object blocksAttr = Files.getAttribute( file, "unix:blocks", LinkOption.NOFOLLOW_LINKS );
216+
if ( blocksAttr instanceof Number )
217+
return ( ( Number ) blocksAttr ).longValue() * 512L; // du uses 512-byte blocks
218+
}
219+
catch ( IllegalArgumentException | UnsupportedOperationException e )
220+
{
221+
// ignore and fall back to logical size
222+
}
223+
return Files.size( file );
224+
}
225+
226+
// --- Windows / fallback: logical file sizes only ---
227+
private static long calculateFileLengthRecursive( File directory )
133228
{
134229
long size = 0;
135230
File[] files = directory.listFiles();
136231
if ( files != null )
232+
{
137233
for ( File file : files )
138-
size += file.isFile() ? file.length() : calculateDirectorySize( file );
234+
{
235+
if ( Files.isSymbolicLink( file.toPath() ) )
236+
continue;
237+
if ( file.isFile() )
238+
size += file.length();
239+
else if ( file.isDirectory() )
240+
size += calculateFileLengthRecursive( file );
241+
}
242+
}
139243
return size;
140244
}
141245
}

0 commit comments

Comments
 (0)