@@ -21,7 +21,7 @@ use std::iter;
2121use std:: num:: ParseIntError ;
2222use std:: path:: Path ;
2323use uucore:: error:: USimpleError ;
24- use uucore:: error:: { FromIo , UError , UResult } ;
24+ use uucore:: error:: { set_exit_code , FromIo , UError , UResult } ;
2525use uucore:: sum:: {
2626 Blake2b , Blake3 , Digest , DigestWriter , Md5 , Sha1 , Sha224 , Sha256 , Sha384 , Sha3_224 , Sha3_256 ,
2727 Sha3_384 , Sha3_512 , Sha512 , Shake128 , Shake256 ,
@@ -46,6 +46,7 @@ struct Options {
4646 warn : bool ,
4747 output_bits : usize ,
4848 zero : bool ,
49+ ignore_missing : bool ,
4950}
5051
5152/// Creates a Blake2b hasher instance based on the specified length argument.
@@ -345,6 +346,12 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
345346 let strict = matches. get_flag ( "strict" ) ;
346347 let warn = matches. get_flag ( "warn" ) && !status;
347348 let zero = matches. get_flag ( "zero" ) ;
349+ let ignore_missing = matches. get_flag ( "ignore-missing" ) ;
350+
351+ if ignore_missing && !check {
352+ // --ignore-missing needs -c
353+ return Err ( HashsumError :: IgnoreNotCheck . into ( ) ) ;
354+ }
348355
349356 let opts = Options {
350357 algoname : name,
@@ -359,6 +366,7 @@ pub fn uumain(mut args: impl uucore::Args) -> UResult<()> {
359366 strict,
360367 warn,
361368 zero,
369+ ignore_missing,
362370 } ;
363371
364372 match matches. get_many :: < OsString > ( "FILE" ) {
@@ -431,6 +439,12 @@ pub fn uu_app_common() -> Command {
431439 . help ( "exit non-zero for improperly formatted checksum lines" )
432440 . action ( ArgAction :: SetTrue ) ,
433441 )
442+ . arg (
443+ Arg :: new ( "ignore-missing" )
444+ . long ( "ignore-missing" )
445+ . help ( "don't fail or report status for missing files" )
446+ . action ( ArgAction :: SetTrue ) ,
447+ )
434448 . arg (
435449 Arg :: new ( "warn" )
436450 . short ( 'w' )
@@ -564,6 +578,7 @@ fn uu_app(binary_name: &str) -> Command {
564578enum HashsumError {
565579 InvalidRegex ,
566580 InvalidFormat ,
581+ IgnoreNotCheck ,
567582}
568583
569584impl Error for HashsumError { }
@@ -574,6 +589,10 @@ impl std::fmt::Display for HashsumError {
574589 match self {
575590 Self :: InvalidRegex => write ! ( f, "invalid regular expression" ) ,
576591 Self :: InvalidFormat => Ok ( ( ) ) ,
592+ Self :: IgnoreNotCheck => write ! (
593+ f,
594+ "the --ignore-missing option is meaningful only when verifying checksums"
595+ ) ,
577596 }
578597 }
579598}
@@ -705,13 +724,19 @@ where
705724 let ( ck_filename_unescaped, prefix) = unescape_filename ( & ck_filename) ;
706725 let f = match File :: open ( ck_filename_unescaped) {
707726 Err ( _) => {
727+ if options. ignore_missing {
728+ // No need to show or return an error.
729+ continue ;
730+ }
731+
708732 failed_open_file += 1 ;
709733 println ! (
710734 "{}: {}: No such file or directory" ,
711735 uucore:: util_name( ) ,
712736 ck_filename
713737 ) ;
714738 println ! ( "{ck_filename}: FAILED open or read" ) ;
739+ set_exit_code ( 1 ) ;
715740 continue ;
716741 }
717742 Ok ( file) => file,
0 commit comments