Как удалить префикс \\? \ Из канонического пути Windows? - PullRequest
0 голосов
/ 14 мая 2018

В Windows Path::canonicalize() возвращает путь в формате:

\\\\?\\C:\\projects\\3rdparty\\rust...

Это потому, что это правильный канонический путь, и он допускает «длинные» пути в Windows (см. Почему мой канонизированный путь имеет префикс \\? \ ).

Однако это не удобный путь, и люди не понимают его.

Для отображения и ведения журнала как я могу легко удалить этот префикс независимо от общей платформы?

Path::components вернет компонент \\?\C: в качестве первого компонента ...

Должен ли я преобразовать это в &str и использовать регулярное выражение? Есть ли какой-то другой, более эргономичный метод удаления префикса, например, какой-то тип с реализацией Display, который автоматически делает правильные вещи?

Мои требования конкретно:

  • Правильно отображает X:\\... для канонического пути в Windows.
  • Не портит платформы, отличные от Windows (например, извлекает или изменяет компоненты пути)

Пример:

use std::path::{Path, PathBuf};

fn simple_path<P: AsRef<Path>>(p: P) -> String {
    String::from(p.as_ref().to_str().unwrap()) // <-- ?? What to do here?
}

pub fn main() {
    let path = PathBuf::from("C:\temp").canonicalize().unwrap();
    let display_path = simple_path(path);
    println!("Output: {}", display_path);
}

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Использование dunce ящик :

extern crate dunce;
…
let compatible_path = dunce::canonicalize(&any_path);

Простое удаление \\?\ может дать неправильные / недопустимые пути. Ящик для грузовых автомобилей проверяет, совместим ли путь UNC, и преобразует путь точно, когда это возможно. Он проходит через все другие пути. Он компилируется в обычный fs::canonicalize() на не-Windows.

0 голосов
/ 14 мая 2018

Прямой ответ - выполнить анализ строки для конкретной платформы:

use std::path::{Path, PathBuf};

#[cfg(not(target_os = "windows"))]
fn adjust_canonicalization<P: AsRef<Path>>(p: P) -> String {
    p.as_ref().display().to_string()
}

#[cfg(target_os = "windows")]
fn adjust_canonicalization<P: AsRef<Path>>(p: P) -> String {
    const VERBATIM_PREFIX: &str = r#"\\?\"#;
    let p = p.as_ref().display().to_string();
    if p.starts_with(VERBATIM_PREFIX) {
        p[VERBATIM_PREFIX.len()..].to_string()
    } else {
        p
    }
}

pub fn main() {
    let path = PathBuf::from(r#"C:\Windows\System32"#)
        .canonicalize()
        .unwrap();
    let display_path = adjust_canonicalization(path);
    println!("Output: {}", display_path);
}

Кстати, я не согласен с тем, что ваша предпосылка - хорошая идея. Проводник Windows отлично справляется с этими дословными путями, и я думаю, что пользователи могут справиться и с ним.

Для [...] ведения журнала

Это звучит как ужасная идея. Если вы что-то регистрируете, вы хотите знать точный путь , а не какой-то потенциально неверный путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...