fn basename<'a>(path: &'a str, sep: char) -> Cow<'a, str> {    let pieces = path.split(sep);    match pieces.last() {        Some(p) => p.into(),        None => path.into(),    }}Usage:println!('{}', basename(foo, '/'));    // outputs 'foo'println!('{}', basename(bob/, '/'));   // outputs ''println!('{}', basename(/usr/local/bin/rustc, '/')); // outputs 'rustc'I think the split() into a match on last() is kind of elegant.I know there is some work needed to handle both str and String, I am not sold on the use of Cow and needing to define a lifetime for the string.I am not sold on Cow because later on I need to extract from it.let prog = basename(&args[0], '/').into_owned();It feels like I am working too hard.
Extracting the last component (basename) of a filesystem path
strings;memory management;url;rust
Firstly, you should use rsplit and next rather than split and last, as it starts at the more appropriate end:fn basename<'a>(path: &'a str, sep: char) -> Cow<'a, str> {    let pieces = path.rsplit(sep);    match pieces.next() {        Some(p) => p.into(),        None => path.into(),    }}Secondly, you shouldnt be using strings for this; you should be using paths, because thats semantically what youre dealing with.The easiest way to get a path tends to be to take a &Path or a generic parameter implementing AsRef<Path> and calling .as_ref() on it; str, String, Path, PathBuf and more implement it.You can get the base name from a &Path with file_name; this admittedly produces a Option<&OsStr>, so if you want to display the path youd need to convert it back towards a string with e.g. .and_then(|s| s.to_str()).Anyway, the point of this latter part is just that for something that is semantically a path, you should be handling it specially, as a rule; a path need not be Unicode. Think on it more.