mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 03:57:44 +00:00
ls: Escape dirname in recursive mode when it has a colon
This commit is contained in:
parent
317f6d9a4a
commit
3c5a419537
2 changed files with 48 additions and 15 deletions
|
@ -55,7 +55,7 @@ use uucore::libc::{dev_t, major, minor};
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
use uucore::libc::{S_IXGRP, S_IXOTH, S_IXUSR};
|
||||||
use uucore::line_ending::LineEnding;
|
use uucore::line_ending::LineEnding;
|
||||||
use uucore::quoting_style::{escape_name, QuotingStyle};
|
use uucore::quoting_style::{escape_dir_name, escape_name, QuotingStyle};
|
||||||
use uucore::{
|
use uucore::{
|
||||||
display::Quotable,
|
display::Quotable,
|
||||||
error::{set_exit_code, UError, UResult},
|
error::{set_exit_code, UError, UResult},
|
||||||
|
@ -2036,14 +2036,27 @@ impl PathData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Show the directory name in the case where several arguments are given to ls
|
||||||
|
/// or the recursive flag is passed.
|
||||||
|
///
|
||||||
|
/// ```no-exec
|
||||||
|
/// $ ls -R
|
||||||
|
/// .: <- This is printed by this function
|
||||||
|
/// dir1 file1 file2
|
||||||
|
///
|
||||||
|
/// dir1: <- This as well
|
||||||
|
/// file11
|
||||||
|
/// ```
|
||||||
fn show_dir_name(path_data: &PathData, out: &mut BufWriter<Stdout>, config: &Config) {
|
fn show_dir_name(path_data: &PathData, out: &mut BufWriter<Stdout>, config: &Config) {
|
||||||
if config.hyperlink && !config.dired {
|
let escaped_name = escape_dir_name(path_data.p_buf.as_os_str(), &config.quoting_style);
|
||||||
let name = escape_name(path_data.p_buf.as_os_str(), &config.quoting_style);
|
|
||||||
let hyperlink = create_hyperlink(&name, path_data);
|
let name = if config.hyperlink && !config.dired {
|
||||||
write!(out, "{hyperlink}:").unwrap();
|
create_hyperlink(&escaped_name, path_data)
|
||||||
} else {
|
} else {
|
||||||
write!(out, "{}:", path_data.p_buf.display()).unwrap();
|
escaped_name
|
||||||
}
|
};
|
||||||
|
|
||||||
|
write!(out, "{name}:").unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
|
@ -2327,9 +2340,10 @@ fn enter_directory(
|
||||||
for e in entries
|
for e in entries
|
||||||
.iter()
|
.iter()
|
||||||
.skip(if config.files == Files::All { 2 } else { 0 })
|
.skip(if config.files == Files::All { 2 } else { 0 })
|
||||||
.filter(|p| p.ft.get().is_some())
|
.filter(|p| {
|
||||||
.filter(|p| p.ft.get().unwrap().is_some())
|
p.ft.get()
|
||||||
.filter(|p| p.ft.get().unwrap().unwrap().is_dir())
|
.is_some_and(|o_ft| o_ft.is_some_and(|ft| ft.is_dir()))
|
||||||
|
})
|
||||||
{
|
{
|
||||||
match fs::read_dir(&e.p_buf) {
|
match fs::read_dir(&e.p_buf) {
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
@ -123,7 +123,7 @@ impl EscapedChar {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_c(c: char, quotes: Quotes) -> Self {
|
fn new_c(c: char, quotes: Quotes, dirname: bool) -> Self {
|
||||||
use EscapeState::*;
|
use EscapeState::*;
|
||||||
let init_state = match c {
|
let init_state = match c {
|
||||||
'\x07' => Backslash('a'),
|
'\x07' => Backslash('a'),
|
||||||
|
@ -142,10 +142,11 @@ impl EscapedChar {
|
||||||
Quotes::Double => Backslash('"'),
|
Quotes::Double => Backslash('"'),
|
||||||
_ => Char('"'),
|
_ => Char('"'),
|
||||||
},
|
},
|
||||||
' ' => match quotes {
|
' ' if !dirname => match quotes {
|
||||||
Quotes::None => Backslash(' '),
|
Quotes::None => Backslash(' '),
|
||||||
_ => Char(' '),
|
_ => Char(' '),
|
||||||
},
|
},
|
||||||
|
':' if dirname => Backslash(':'),
|
||||||
_ if c.is_ascii_control() => Octal(EscapeOctal::from(c)),
|
_ if c.is_ascii_control() => Octal(EscapeOctal::from(c)),
|
||||||
_ => Char(c),
|
_ => Char(c),
|
||||||
};
|
};
|
||||||
|
@ -285,7 +286,10 @@ fn shell_with_escape(name: &str, quotes: Quotes) -> (String, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Escape a name according to the given quoting style.
|
/// Escape a name according to the given quoting style.
|
||||||
pub fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
|
///
|
||||||
|
/// This inner function provides an additional flag `dirname` which
|
||||||
|
/// is meant for ls' directory name display.
|
||||||
|
fn escape_name_inner(name: &OsStr, style: &QuotingStyle, dirname: bool) -> String {
|
||||||
match style {
|
match style {
|
||||||
QuotingStyle::Literal { show_control } => {
|
QuotingStyle::Literal { show_control } => {
|
||||||
if *show_control {
|
if *show_control {
|
||||||
|
@ -301,7 +305,7 @@ pub fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
|
||||||
let escaped_str: String = name
|
let escaped_str: String = name
|
||||||
.to_string_lossy()
|
.to_string_lossy()
|
||||||
.chars()
|
.chars()
|
||||||
.flat_map(|c| EscapedChar::new_c(c, *quotes))
|
.flat_map(|c| EscapedChar::new_c(c, *quotes, dirname))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
match quotes {
|
match quotes {
|
||||||
|
@ -316,7 +320,10 @@ pub fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
|
||||||
show_control,
|
show_control,
|
||||||
} => {
|
} => {
|
||||||
let name = name.to_string_lossy();
|
let name = name.to_string_lossy();
|
||||||
let (quotes, must_quote) = if name.contains(&['"', '`', '$', '\\'][..]) {
|
|
||||||
|
// Take ':' in account only if we are quoting a dirname
|
||||||
|
let start_index = if dirname { 0 } else { 1 };
|
||||||
|
let (quotes, must_quote) = if name.contains(&[':', '"', '`', '$', '\\'][start_index..]) {
|
||||||
(Quotes::Single, true)
|
(Quotes::Single, true)
|
||||||
} else if name.contains('\'') {
|
} else if name.contains('\'') {
|
||||||
(Quotes::Double, true)
|
(Quotes::Double, true)
|
||||||
|
@ -341,6 +348,18 @@ pub fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Escape a filename with respect to the given style.
|
||||||
|
pub fn escape_name(name: &OsStr, style: &QuotingStyle) -> String {
|
||||||
|
escape_name_inner(name, style, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Escape a directory name with respect to the given style.
|
||||||
|
/// This is mainly meant to be used for ls' directory name printing and is not
|
||||||
|
/// likely to be used elsewhere.
|
||||||
|
pub fn escape_dir_name(dir_name: &OsStr, style: &QuotingStyle) -> String {
|
||||||
|
escape_name_inner(dir_name, style, true)
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for QuotingStyle {
|
impl fmt::Display for QuotingStyle {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue