diff --git a/src/find/main.rs b/src/find/main.rs index 552ab494..b9e4eda8 100644 --- a/src/find/main.rs +++ b/src/find/main.rs @@ -25,7 +25,8 @@ fn main() { Ok(args) => args, Err(invalid) => { eprintln!( - "find: invalid (non-UTF-8) argument: {}", + "{}: invalid (non-UTF-8) argument: {}", + findutils::find::program_name(), invalid.to_string_lossy() ); std::process::exit(1); diff --git a/src/find/matchers/printf.rs b/src/find/matchers/printf.rs index 313d22f1..ac6d9abc 100644 --- a/src/find/matchers/printf.rs +++ b/src/find/matchers/printf.rs @@ -205,7 +205,10 @@ impl FormatStringParser<'_> { '0' => "\0", '\\' => "\\", c => { - eprintln!("find: warning: unrecognized escape '\\{c}'"); + eprintln!( + "{}: warning: unrecognized escape '\\{c}'", + crate::find::program_name() + ); return Ok(FormatComponent::Literal(format!("\\{c}"))); } }; @@ -317,7 +320,10 @@ impl FormatStringParser<'_> { 'Y' => FormatDirective::Type { follow_links: true }, // TODO: %Z _ => { - eprintln!("find: warning: unrecognized format directive '%{first}'"); + eprintln!( + "{}: warning: unrecognized format directive '%{first}'", + crate::find::program_name() + ); return Ok(FormatComponent::Literal(format!("%{first}"))); } }; @@ -650,9 +656,14 @@ impl Printf { } if let Some((_, path)) = &self.output_file { - let _ = writeln!(&mut stderr(), "find: {}: {error}", path.display()); + let _ = writeln!( + &mut stderr(), + "{}: {}: {error}", + crate::find::program_name(), + path.display() + ); } else { - let _ = writeln!(&mut stderr(), "find: {error}"); + let _ = writeln!(&mut stderr(), "{}: {error}", crate::find::program_name()); } matcher_io.set_exit_code(1); } diff --git a/src/find/mod.rs b/src/find/mod.rs index 0cab6e82..cbc49f7c 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -194,7 +194,7 @@ impl Iterator for Files0Paths { } if buffer.is_empty() { // Skip it so as to avoid a file not found error. - eprintln!("find: invalid zero-length file name"); + eprintln!("{}: invalid zero-length file name", program_name()); continue; } return Some(String::from_utf8(buffer).map_err(Into::into)); @@ -492,6 +492,23 @@ fn print_version(deps: &dyn Dependencies) -> Result<(), io::Error> { ) } +/// The name `find` was invoked as, for prefixing its messages: the base name +/// of argv[0], without the `.exe` that Windows executables carry. +pub fn program_name() -> &'static str { + let name = uucore::util_name(); + let path = std::path::Path::new(name); + if cfg!(windows) + && path + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("exe")) + { + if let Some(stem) = path.file_stem().and_then(std::ffi::OsStr::to_str) { + return stem; + } + } + name +} + /// Does all the work for find. /// /// All main has to do is pass in the command-line args and exit the process @@ -501,7 +518,7 @@ pub fn find_main(args: &[&str], deps: &dyn Dependencies) -> i32 { match do_find(&args[1..], deps) { Ok(ret) => ret, Err(e) => { - writeln!(&mut stderr(), "find: {e}").unwrap(); + writeln!(&mut stderr(), "{}: {e}", program_name()).unwrap(); 1 } }