如何在Rust中处理Windows WSL2环境下的文件路径问题
WSL路径下的Rust文件重命名库问题
背景
我正在开发一个用于交换任意两个文件文件名的Rust库,但在处理WSL环境下的文件路径时遇到了问题。
预期行为示例
1. 正常情况
| 状态 | 文件1 | 文件2 |
|---|---|---|
| 重命名前 | D:\test\1.ext1 | D:\test\2.ext2 |
| 重命名后 | D:\test\2.ext1 | D:\test\1.ext2 |
2. 相对路径情况
| 状态 | 文件1 | 文件2 |
|---|---|---|
| 重命名前 | ./1.ext1 | ~/2.ext2 |
| 重命名后 | D:\test\2.ext1 | C:\Users\xxx\1.ext2 |
3. WSL路径情况
| 状态 | 文件1 | 文件2 |
|---|---|---|
| 重命名前 | \\wsl.localhost\Debian\home\user1\1.ext1 | \\wsl.localhost\Debian\home\user1\2.ext2 |
| 重命名后(预期结果) | \\wsl.localhost\Debian\home\user1\2.ext1 | \\wsl.localhost\Debian\home\user1\1.ext2 |
最小可复现代码(MWE)
use std::path::{Path, PathBuf}; fn main() { // 请在你的WSL环境中创建这个测试文件:`~/1.ext1` // 请修改此处为你的WSL用户名 let wsl_user_name = ""; // 请在Windows的工作目录中创建这个测试文件:`./2.ext2` let current_exe = std::env::current_exe().unwrap(); let base_dir = current_exe.parent().unwrap(); let wsl_file = PathBuf::from(format!( r"\\wsl.localhost\Debian\home\{}\1.ext1", wsl_user_name )); let win_file = PathBuf::from(r"./2.ext2"); let result_wsl = path_get_absolute_exist(&wsl_file, base_dir); dbg!(result_wsl); let result_win = path_get_absolute_exist(&win_file, base_dir); dbg!(result_win); } fn path_get_absolute_exist(path: &Path, base_dir: &Path) -> (bool, PathBuf) { if path.as_os_str().is_empty() { return (false, path.to_path_buf()); } let mut path = path.to_path_buf(); #[cfg(windows)] { use std::path::{Component, Prefix}; path = { let temp = path.to_str().unwrap_or("").replace("/", "\\"); PathBuf::from(temp) }; let is_absolute = { let mut components = path.components(); if let Some(Component::Prefix(prefix_component)) = components.next() { let has_root_dir = matches!(components.next(), Some(Component::RootDir)); dbg!(has_root_dir); if !has_root_dir { false } else { dbg!(prefix_component.kind()); matches!( prefix_component.kind(), // 判断`\\wsl.localhost\`有用,但判断文件是否存在时没用 Prefix::VerbatimUNC(..) | Prefix::UNC(..) | Prefix::VerbatimDisk(..) | Prefix::Disk(_) | Prefix::DeviceNS(..) | Prefix::Verbatim(_) ) } } else { dbg!(path.is_absolute()); path.is_absolute() } }; if !is_absolute { if path.starts_with("~") { if let Ok(home_dir) = std::env::var("USERPROFILE") { let mut new_path = PathBuf::from(home_dir); let remaining = path.strip_prefix("~/").ok(); if let Some(rem) = remaining { new_path.push(rem); path = new_path; } else if path.to_string_lossy() == "~" { path = new_path; } else { // 处理"~something"这类格式 path = base_dir.join(path); } } } else { path = base_dir.join(path); } } dbg!(format!("最终路径: {}", &path.display())); } #[cfg(not(windows))] { path = { let temp = path.to_str().unwrap_or("").replace("\\", "/"); PathBuf::from(temp) }; if !path.is_absolute() { if path.starts_with("~") { if let Ok(home_dir) = std::env::var("HOME") { let mut new_path = PathBuf::from(home_dir); if let Some(remaining) = path.strip_prefix("~/").ok() { new_path.push(remaining); } else if path.to_string_lossy() == "~" { // 仅为"~"时,直接使用主目录 } path = new_path; } } else { path = base_dir.join(path); } } dbg!(format!("最终路径: {}", &path.display())); } let canonical = path.canonicalize(); match canonical { Ok(x) => (x.exists(), x), Err(e) => { eprintln!("{}", e); (path.exists(), path) } } }
错误信息
[src\exchange.rs:161:13] is_absolute = true [src\exchange.rs:190:9] &path = "\\\\wsl.localhost\\Debian\\home\\user1\\1.ext1" [src\exchange.rs:161:13] is_absolute = true [src\exchange.rs:190:9] &path = "\\\\wsl.localhost\\Debian\\home\\user1\\2.ext2" File does not exist
内容的提问来源于stack exchange,提问作者LinkChou
相关产品推荐
相关产品推荐

