Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to find dead symlinks #1641

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion doc/fd.1
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ Searching for '--type file --type symlink' will show both regular files as well
symlinks. Note that the 'executable' and 'empty' filters work differently: '--type
executable' implies '--type file' by default. And '--type empty' searches for
empty files and directories, unless either '--type file' or '--type directory' is
specified in addition.
specified in addition to search for that type only, or '--type symlink' is
specified in addition to search for dead symlinks.

Examples:
- Only search for files:
Expand All @@ -241,6 +242,9 @@ Examples:
- Find empty directories:
fd --type empty --type directory
fd -te -td
- Find dead symlinks:
fd --type empty --type symlink
fd -te -tl
.RE
.TP
.BI "\-e, \-\-extension " ext
Expand Down
6 changes: 5 additions & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ pub struct Opts {
/// well as symlinks. Note that the 'executable' and 'empty' filters work differently:
/// '--type executable' implies '--type file' by default. And '--type empty' searches
/// for empty files and directories, unless either '--type file' or '--type directory'
/// is specified in addition.
/// is specified in addition to search for that type only, or '--type symlink' is
/// specified in addition to search for dead symlinks.
///
/// Examples:
/// {n} - Only search for files:
Expand All @@ -346,6 +347,9 @@ pub struct Opts {
/// {n} - Find empty directories:
/// {n} fd --type empty --type directory
/// {n} fd -te -td
/// {n} - Find dead symlinks:
/// {n} fd --type empty --type symlink
/// {n} fd -te -tl
#[arg(
long = "type",
short = 't',
Expand Down
13 changes: 12 additions & 1 deletion src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fs;
use std::io;
#[cfg(any(unix, target_os = "redox"))]
use std::os::unix::fs::FileTypeExt;
use std::path::{Path, PathBuf};
use std::path::{Path, PathBuf, MAIN_SEPARATOR_STR};

use normpath::PathExt;

Expand Down Expand Up @@ -51,6 +51,17 @@ pub fn is_empty(entry: &dir_entry::DirEntry) -> bool {
}
} else if file_type.is_file() {
entry.metadata().map(|m| m.len() == 0).unwrap_or(false)
} else if file_type.is_symlink() {
if let Ok(target) = entry.path().read_link() {
let full_target = entry
.path()
.parent()
.unwrap_or(Path::new(MAIN_SEPARATOR_STR))
.join(target);
!full_target.exists()
} else {
false
}
} else {
false
}
Expand Down
4 changes: 3 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,9 @@ fn construct_config(mut opts: Opts, pattern_regexps: &[String]) -> Result<Config
}

// If only 'empty' was specified, search for both files and directories:
if file_types.empty_only && !(file_types.files || file_types.directories) {
if file_types.empty_only
&& !(file_types.files || file_types.directories || file_types.symlinks)
{
file_types.files = true;
file_types.directories = true;
}
Expand Down
Loading