Repository: sharkdp/fd (language: rust)

Issue:
Incomplete file-type handling
I was looking for sockets, but noticed some other file types are missing as well.

From `find`:
```
     -type t
             True if the file is of the specified type.  Possible file types are as follows:

             b       block special
             c       character special
             d       directory
             f       regular file
             l       symbolic link
             p       FIFO
             s       socket
```
equivalently, via the Open Group [sys/stat.h](https://pubs.opengroup.org/onlinepubs/009604499/basedefs/sys/stat.h.html) linked from Wikipedia
```
S_IFMT  Type of file.
  S_IFBLK   Block special.
  S_IFCHR   Character special.
  S_IFIFO   FIFO special.
  S_IFREG   Regular.
  S_IFDIR   Directory.
  S_IFLNK   Symbolic link.
  S_IFSOCK  Socket.
```

For reference, `fd` offers the following filetype filters currently, according to `--help`:
```
    -t, --type <filetype>...
            Filter the search by type (multiple allowable filetypes can be specified):
              'f' or 'file':         regular files
              'd' or 'directory':    directories
              'l' or 'symlink':      symbolic links
              'x' or 'executable':   executables
              'e' or 'empty':        empty files or directories
```


Discussion / hints:
Thank you for the feedback. The problem is that sockets, FIFOs, etc. are specific to Unix-like operating systems, whereas `fd` tries to be platform independent.

Sure, we could add OS-specific features, but that would complicate a lot of things (the code base, documentation, testing).
I'm not sure if it would meet @mcint's needs, but what if there was a "special" type to match files that are not "normal", which would include sockets, fifos, character/block special files, etc. on unix, and any similar os-specific specail files on windows if there are any.
The question is if this is really a 80% use case (or even a 99% use case) or if this is just a request to add these filetypes "for completeness".

So far, I've never found myself in the need to search for sockets or FIFOs - but obviously that doesn't mean that we should definitely not add this to `fd`.
> The question is if this is really a 80% use case (or even a 99% use case) or if this is just a request to add these filetypes "for completeness".

Not saying this to be demanding, but I personally needed this today. I was `tar`ing some stuff and realized `tar format cannot archive socket` (understandably). I wanted to figure out which files were causing that and assumed I could depend on `fd` (which, other than this issue, has been a complete godsend).

Of course I can't speak to how much usage this would actually get, but I would say that this is a non-existing feature I find harder to work around than other (in comparison to `find`) missing features.

> Thank you for the feedback. The problem is that sockets, FIFOs, etc. are specific to Unix-like operating systems, whereas fd tries to be platform independent.

I definitely understand that tho (in the general, I personally value Unix-portability more than Windows-compatibility). I respect your decision either way.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ccc1af6b2..a2e566f8c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,9 +12,10 @@
   This can be useful to speed up searches in cases where you know that there are only N results.
   Using this option is also (slightly) faster than piping to `head -n <count>` where `fd` can only
   exit when it finds the search results `<count> + 1`.
+- Add the alias `-1` for `--max-results=1`, see #561. (@SimplyDanny).
+- Add new `--type socket` and `--type pipe` filters, see #511.
 - Add new `--min-depth <depth>` and `--exact-depth <depth>` options in addition to the existing option
   to limit the maximum depth. See #404.
-- Add the alias `-1` for `--max-results=1`, see #561. (@SimplyDanny).
 - Support additional ANSI font styles in `LS_COLORS`: faint, slow blink, rapid blink, dimmed, hidden and strikethrough.
 
 ## Bugfixes
diff --git a/doc/fd.1 b/doc/fd.1
index 6575c2a4f..3c31cd753 100644
--- a/doc/fd.1
+++ b/doc/fd.1
@@ -129,6 +129,10 @@ symbolic links
 executable (files)
 .IP "e, empty"
 empty files or directories
+.IP "s, socket"
+sockets
+.IP "p, pipe"
+named pipes (FIFOs)
 .RE
 
 .RS
diff --git a/src/app.rs b/src/app.rs
index 3b33d0ee9..7ca02715d 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -228,11 +228,15 @@ pub fn build_app() -> App<'static, 'static> {
                     "executable",
                     "e",
                     "empty",
+                    "s",
+                    "socket",
+                    "p",
+                    "pipe",
                 ])
                 .hide_possible_values(true)
                 .help(
                     "Filter by type: file (f), directory (d), symlink (l),\nexecutable (x), \
-                         empty (e)",
+                         empty (e), socket (s), pipe (p)",
                 )
                 .long_help(
                     "Filter the search by type (multiple allowable filetypes can be specified):\n  \
@@ -240,7 +244,9 @@ pub fn build_app() -> App<'static, 'static> {
                        'd' or 'directory':    directories\n  \
                        'l' or 'symlink':      symbolic links\n  \
                        'x' or 'executable':   executables\n  \
-                       'e' or 'empty':        empty files or directories",
+                       'e' or 'empty':        empty files or directories\n  \
+                       's' or 'socket':       socket\n  \
+                       'p' or 'pipe':         named pipe (FIFO)",
                 ),
         )
         .arg(
diff --git a/src/filesystem.rs b/src/filesystem.rs
index a43527f72..a41fd58e0 100644
--- a/src/filesystem.rs
+++ b/src/filesystem.rs
@@ -4,7 +4,7 @@ use std::ffi::OsStr;
 use std::fs;
 use std::io;
 #[cfg(any(unix, target_os = "redox"))]
-use std::os::unix::fs::PermissionsExt;
+use std::os::unix::fs::{PermissionsExt, FileTypeExt};
 use std::path::{Path, PathBuf};
 
 use crate::walk;
@@ -67,6 +67,26 @@ pub fn is_empty(entry: &walk::DirEntry) -> bool {
     }
 }
 
+#[cfg(any(unix, target_os = "redox"))]
+pub fn is_socket(ft: &fs::FileType) -> bool {
+    ft.is_socket()
+}
+
+#[cfg(windows)]
+pub fn is_socket(_: &fs::FileType) -> bool {
+    false
+}
+
+#[cfg(any(unix, target_os = "redox"))]
+pub fn is_pipe(ft: &fs::FileType) -> bool {
+    ft.is_fifo()
+}
+
+#[cfg(windows)]
+pub fn is_pipe(_: &fs::FileType) -> bool {
+    false
+}
+
 #[cfg(any(unix, target_os = "redox"))]
 pub fn osstr_to_bytes(input: &OsStr) -> Cow<[u8]> {
     use std::os::unix::ffi::OsStrExt;
diff --git a/src/filetypes.rs b/src/filetypes.rs
index f2703c8e3..1f445da4d 100644
--- a/src/filetypes.rs
+++ b/src/filetypes.rs
@@ -3,6 +3,8 @@ pub struct FileTypes {
     pub files: bool,
     pub directories: bool,
     pub symlinks: bool,
+    pub sockets: bool,
+    pub pipes: bool,
     pub executables_only: bool,
     pub empty_only: bool,
 }
@@ -13,6 +15,8 @@ impl Default for FileTypes {
             files: false,
             directories: false,
             symlinks: false,
+            sockets: false,
+            pipes: false,
             executables_only: false,
             empty_only: false,
         }
diff --git a/src/main.rs b/src/main.rs
index 969ffbcf9..fb64e7a7b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -317,9 +317,9 @@ fn run() -> Result<ExitCode> {
                         file_types.executables_only = true;
                         file_types.files = true;
                     }
-                    "e" | "empty" => {
-                        file_types.empty_only = true;
-                    }
+                    "e" | "empty" => file_types.empty_only = true,
+                    "s" | "socket" => file_types.sockets = true,
+                    "p" | "pipe" => file_types.pipes = true,
                     _ => unreachable!(),
                 }
             }
diff --git a/src/walk.rs b/src/walk.rs
index 34b862c21..93f20dec0 100644
--- a/src/walk.rs
+++ b/src/walk.rs
@@ -390,13 +390,19 @@ fn spawn_senders(
                     if (!file_types.files && entry_type.is_file())
                         || (!file_types.directories && entry_type.is_dir())
                         || (!file_types.symlinks && entry_type.is_symlink())
+                        || (!file_types.sockets && filesystem::is_socket(entry_type))
+                        || (!file_types.pipes && filesystem::is_pipe(entry_type))
                         || (file_types.executables_only
                             && !entry
                                 .metadata()
                                 .map(|m| filesystem::is_executable(&m))
                                 .unwrap_or(false))
                         || (file_types.empty_only && !filesystem::is_empty(&entry))
-                        || !(entry_type.is_file() || entry_type.is_dir() || entry_type.is_symlink())
+                        || !(entry_type.is_file()
+                            || entry_type.is_dir()
+                            || entry_type.is_symlink()
+                            || filesystem::is_socket(entry_type)
+                            || filesystem::is_pipe(entry_type))
                     {
                         return ignore::WalkState::Continue;
                     }


Test patch: