@@ -30,8 +30,11 @@ use uucore::line_ending::LineEnding;
3030use uucore:: safe_traversal:: DirFd ;
3131use uucore:: translate;
3232
33+ use uucore:: format:: human:: format_with_thousands_separator;
3334use uucore:: parser:: parse_glob;
34- use uucore:: parser:: parse_size:: { ParseSizeError , parse_size_non_zero_u64, parse_size_u64} ;
35+ use uucore:: parser:: parse_size:: {
36+ ParseSizeError , extract_thousands_separator_flag, parse_size_non_zero_u64, parse_size_u64,
37+ } ;
3538use uucore:: parser:: shortcut_value_parser:: ShortcutValueParser ;
3639use uucore:: time:: { FormatSystemTimeFallback , format, format_system_time} ;
3740use uucore:: { format_usage, show, show_error, show_warning} ;
@@ -91,6 +94,7 @@ struct StatPrinter {
9194 threshold : Option < Threshold > ,
9295 apparent_size : bool ,
9396 size_format : SizeFormat ,
97+ use_thousands_separator : bool ,
9498 time : Option < MetadataTimeField > ,
9599 time_format : String ,
96100 line_ending : LineEnding ,
@@ -271,26 +275,33 @@ fn get_file_info(path: &Path, _metadata: &Metadata) -> Option<FileInfo> {
271275 result
272276}
273277
274- fn block_size_from_env ( ) -> Option < u64 > {
278+ fn block_size_from_env ( ) -> Option < ( u64 , bool ) > {
275279 for env_var in [ "DU_BLOCK_SIZE" , "BLOCK_SIZE" , "BLOCKSIZE" ] {
276280 if let Ok ( env_size) = env:: var ( env_var) {
277- return parse_size_non_zero_u64 ( & env_size) . ok ( ) ;
281+ let ( cleaned, use_thousands) = extract_thousands_separator_flag ( & env_size) ;
282+ if let Ok ( size) = parse_size_non_zero_u64 ( cleaned) {
283+ return Some ( ( size, use_thousands) ) ;
284+ }
285+ // If env var is set but invalid, return None (don't check other env vars)
286+ return None ;
278287 }
279288 }
280289
281290 None
282291}
283292
284- fn read_block_size ( s : Option < & str > ) -> UResult < u64 > {
293+ fn read_block_size ( s : Option < & str > ) -> UResult < ( u64 , bool ) > {
285294 if let Some ( s) = s {
286- parse_size_u64 ( s)
295+ let ( cleaned, use_thousands) = extract_thousands_separator_flag ( s) ;
296+ parse_size_u64 ( cleaned)
297+ . map ( |size| ( size, use_thousands) )
287298 . map_err ( |e| USimpleError :: new ( 1 , format_error_message ( & e, s, options:: BLOCK_SIZE ) ) )
288- } else if let Some ( bytes) = block_size_from_env ( ) {
289- Ok ( bytes)
299+ } else if let Some ( ( bytes, use_thousands ) ) = block_size_from_env ( ) {
300+ Ok ( ( bytes, use_thousands ) )
290301 } else if env:: var ( "POSIXLY_CORRECT" ) . is_ok ( ) {
291- Ok ( 512 )
302+ Ok ( ( 512 , false ) )
292303 } else {
293- Ok ( 1024 )
304+ Ok ( ( 1024 , false ) )
294305 }
295306}
296307
@@ -874,7 +885,12 @@ impl StatPrinter {
874885 // we ignore block size (-B) with --inodes
875886 size. to_string ( )
876887 } else {
877- size. div_ceil ( block_size) . to_string ( )
888+ let result = size. div_ceil ( block_size) ;
889+ if self . use_thousands_separator {
890+ format_with_thousands_separator ( result)
891+ } else {
892+ result. to_string ( )
893+ }
878894 }
879895 }
880896 }
@@ -1005,24 +1021,24 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
10051021 . map_or ( MetadataTimeField :: Modification , |s| s. as_str ( ) . into ( ) )
10061022 } ) ;
10071023
1008- let size_format = if matches. get_flag ( options:: HUMAN_READABLE ) {
1009- SizeFormat :: HumanBinary
1024+ let ( size_format, use_thousands_separator ) = if matches. get_flag ( options:: HUMAN_READABLE ) {
1025+ ( SizeFormat :: HumanBinary , false )
10101026 } else if matches. get_flag ( options:: SI ) {
1011- SizeFormat :: HumanDecimal
1027+ ( SizeFormat :: HumanDecimal , false )
10121028 } else if matches. get_flag ( options:: BYTES ) {
1013- SizeFormat :: BlockSize ( 1 )
1029+ ( SizeFormat :: BlockSize ( 1 ) , false )
10141030 } else if matches. get_flag ( options:: BLOCK_SIZE_1K ) {
1015- SizeFormat :: BlockSize ( 1024 )
1031+ ( SizeFormat :: BlockSize ( 1024 ) , false )
10161032 } else if matches. get_flag ( options:: BLOCK_SIZE_1M ) {
1017- SizeFormat :: BlockSize ( 1024 * 1024 )
1033+ ( SizeFormat :: BlockSize ( 1024 * 1024 ) , false )
10181034 } else {
10191035 let block_size_str = matches. get_one :: < String > ( options:: BLOCK_SIZE ) ;
1020- let block_size = read_block_size ( block_size_str. map ( AsRef :: as_ref) ) ?;
1036+ let ( block_size, use_thousands ) = read_block_size ( block_size_str. map ( AsRef :: as_ref) ) ?;
10211037 if block_size == 0 {
10221038 return Err ( std:: io:: Error :: other ( translate ! ( "du-error-invalid-block-size-argument" , "option" => options:: BLOCK_SIZE , "value" => block_size_str. map_or( "???BUG" , |v| v) . quote( ) ) )
10231039 . into ( ) ) ;
10241040 }
1025- SizeFormat :: BlockSize ( block_size)
1041+ ( SizeFormat :: BlockSize ( block_size) , use_thousands )
10261042 } ;
10271043
10281044 let traversal_options = TraversalOptions {
@@ -1051,6 +1067,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
10511067 let stat_printer = StatPrinter {
10521068 max_depth,
10531069 size_format,
1070+ use_thousands_separator,
10541071 summarize,
10551072 total : matches. get_flag ( options:: TOTAL ) ,
10561073 inodes : matches. get_flag ( options:: INODES ) ,
@@ -1508,7 +1525,11 @@ mod test_du {
15081525 fn test_read_block_size ( ) {
15091526 let test_data = [ Some ( "1024" . to_string ( ) ) , Some ( "K" . to_string ( ) ) , None ] ;
15101527 for it in & test_data {
1511- assert ! ( matches!( read_block_size( it. as_deref( ) ) , Ok ( 1024 ) ) ) ;
1528+ assert ! ( matches!( read_block_size( it. as_deref( ) ) , Ok ( ( 1024 , false ) ) ) ) ;
15121529 }
1530+
1531+ // Test with thousands separator flag
1532+ assert ! ( matches!( read_block_size( Some ( "'1024" ) ) , Ok ( ( 1024 , true ) ) ) ) ;
1533+ assert ! ( matches!( read_block_size( Some ( "'1K" ) ) , Ok ( ( 1024 , true ) ) ) ) ;
15131534 }
15141535}
0 commit comments