Rust中如何跨操作系统获取文件的创建时间属性
Rust标准库提供的std::fs::Metadata用于获取文件的属性元数据。
以下是示例代码:
use std::fs;
fn main() -> std::io::Result<()> {
let metadata = fs::metadata("foo.txt")?;
if let Ok(time) = metadata.created() {
println!("{time:?}");
} else {
println!("Not supported on this platform or filesystem");
}
Ok(())
}
问题
我在编写跨操作系统服务程序时,发现在我的Mac开发机器上这段代码运行没有问题,但是到了生产环境中的Linux服务器(Ubuntu 20.04.3 LTS - GNU/Linux 5.4.0-100-generic x86_64)上就报错,提示方法不被支持的。
通过查阅官方资料发现:
The returned value corresponds to the
btime
field ofstatx
on Linux kernel starting from to 4.11, thebirthtime
field ofstat
on other Unix platforms, and theftCreationTime
field on Windows platforms.
以及
This field might not be available on all platforms, and will return an Err on platforms or filesystems where it is not available.
资料表明,该调用方法不是所有平台都适用的。
解决方法
经过多次查找资料后发现,标准库还是提供了解决方案的。
在标准库中搜索Metadata
时,发现有很多针对不同操作系统的trait
:
- trait std::os::linux::fs::MetadataExt: 特定于
Linux
操作系统的 - trait std::os::unix::fs::MetadataExt: 特定于
Unix
操作系统的 - trait std::os::wasi::fs::MetadataExt: 特定于
WASI
操作系统的 - trait std::os::windows::fs::MetadataExt: 特定于
Windows
操作系统的
而std::fs::Metadata对这些Trait
进行了实现。
最后在程序中,需要针对不同的操作系统编写如下代码:
use std::fs;
use std::path::Path;
fn main() -> std::io::Result<()> {
let time = get_file_created("foo.txt");
println!("{time:?}");
Ok(())
}
#[cfg(target_os = "unix")]
pub fn get_file_created<P: AsRef<Path>>(path: P) -> i64 {
let meta = fs::metadata(path).unwrap();
use std::os::unix::fs::MetadataExt;
meta.ctime()
}
#[cfg(target_os = "linux")]
pub fn get_file_created<P: AsRef<Path>>(path: P) -> i64 {
let meta = fs::metadata(path).unwrap();
use std::os::linux::fs::MetadataExt;
meta.st_ctime()
}
最后,在我的MacOS
开发机器上和Linux
生产服务器上都测试通过。