Comment by da-x
18 days ago
Alternative, you can check whether there are duplicates under $PATH resolutions - binaries that can come from more than one place in $PATH.
#!/usr/bin/env -S cargo eval --
// cargo-deps: derive-error="0", is_executable="0"
// vi: ft=rust
use derive_error::Error;
use is_executable::IsExecutable;
use std::collections::{BTreeMap, HashSet, btree_map};
use std::os::unix::fs::MetadataExt;
use std::path::{Path, PathBuf};
#[derive(Debug, Error)]
pub enum Error {
VarEnv(std::env::VarError),
Io(std::io::Error),
}
fn main() -> Result<(), Error> {
let mut paths_seen = HashSet::new();
let mut path_fileid_seen = HashSet::new();
let mut exes_seen = BTreeMap::new();
for path in std::env::var("PATH")?.split(":") {
let path = PathBuf::from(path);
if !path.is_dir() {
continue;
}
if !path_fileid_seen.insert(path.metadata()?.ino()) {
continue;
}
if paths_seen.insert(path.clone()) {
match std::fs::read_dir(&path) {
Err(_) => {
eprintln!("error listing {:?}", path);
}
Ok(readdir) => {
for entry in readdir {
let entry = entry?;
if entry.path().is_executable() {
let mut item = match exes_seen.entry(
String::from(entry.path().file_name()
.unwrap().to_string_lossy().as_ref()))
{
btree_map::Entry::Vacant(v) => v.insert(vec![]),
btree_map::Entry::Occupied(o) => o.into_mut(),
};
item.push(path.clone());
}
}
}
}
}
}
for (exe, paths) in exes_seen.into_iter() {
if paths.len() == 2 {
let mut strs = vec![];
for path in paths.iter() {
strs.push(path.to_str().unwrap());
}
if strs.as_slice() == ["/usr/bin", "/usr/sbin"] {
continue;
}
}
if paths.len() > 1 {
println!("{}: ", exe);
for path in paths {
println!(" {}", path.to_str().unwrap());
}
println!("");
}
}
Ok(())
}
No comments yet
Contribute on Hacker News ↗