1

I'm writing a small utility for myself that needs to be able to check if a file is a symlink or not.

Using FileType::is_symlink on Windows always returns false (goes for both symlinks to directories, and regular files).

Using regular Rust 2018 edition, is there any way to check if a file is a symlink on Windows?

In my searching, I came across: FileTypeExt - however this requires that you use unstable Rust, as far as I can tell.

vallentin
  • 23,478
  • 6
  • 59
  • 81
LaVache
  • 2,372
  • 3
  • 24
  • 38
  • 2
    Just checking, did you follow the doc instructions and use `fs::symlink_metadata` to get the file type? – kmdreko Jan 16 '21 at 18:00
  • 1
    Can confirm `fs::symlink_metadata(path)?.file_type().is_symlink()` works on Windows. Whereas using `fs::metadata()` "wouldn't" as it follows the links. – vallentin Jan 16 '21 at 18:05
  • 2
    Also note that saying that you're using Rust 2018 is usually not as useful as giving us the Rust version you're using. The standard library changes a lot across versions. – mcarton Jan 16 '21 at 18:06
  • Thanks to you all. Yes fs::symlink_metadata(path)?.file_type().is_symlink() does actually work. I must have misunderstood that part of the docs. Happy to mark as answer if someone wants to post it. – LaVache Jan 16 '21 at 19:28

1 Answers1

4

Using File::metadata() or fs::metadata() to get the file type will always return false for FileType::is_symlink() because the link has already been followed at that point. The docs note that:

The underlying Metadata struct needs to be retrieved with the fs::symlink_metadata function and not the fs::metadata function. The fs::metadata function follows symbolic links, so is_symlink would always return false for the target file.

use std::fs;

fn main() -> std::io::Result<()> {
    let metadata = fs::symlink_metadata("foo.txt")?;
    let file_type = metadata.file_type();

    let _ = file_type.is_symlink();
    Ok(())
}
vallentin
  • 23,478
  • 6
  • 59
  • 81
kmdreko
  • 42,554
  • 6
  • 57
  • 106