Description
What version of fd
are you using?
[fd 10.2.0]
Apologies if this is the wrong place for this.
Running some simple tests, fd takes roughly the exact amount of time in a vast directory regardless of if --max-depth 1/--exact--depth 1 (--max-depth 0 yields nothing). This makes me think that it simply filters the results but still searches all entries all levels deep? I'm sure I don't fully understand hence my question. If so, why not just limit the iteration to whatever the level is instead? Or maybe just add a '--top-level-only' flag This could cut down on processing time. For context, here is what i'm doing:
private static readonly string[] BaseFdOptions = [
"--print0",
"--full-path",
"--absolute-path",
"--unrestricted"
];
public static Result<List<string>> SearchPathsFd(string searchDir, string searchTerm, EntryType matchType, bool ignoreCase, bool recursive)
{
if (!Directory.Exists(searchDir))
return Result<List<string>>.Failure($"'{searchDir}' does not exist.");
string fdPath = Path.Combine(AppContext.BaseDirectory, "Resources", "fd.exe");
if (!File.Exists(fdPath))
return Result<List<string>>.Failure($"'{fdPath}' does not exist.");
string arguments = BuildFdArguments(searchDir, searchTerm, matchType, ignoreCase, recursive);
try
{
using var process = Process.Start(new ProcessStartInfo
{
FileName = fdPath,
Arguments = arguments,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
StandardOutputEncoding = Encoding.UTF8,
});
using var memoryStream = new MemoryStream();
process.StandardOutput.BaseStream.CopyTo(memoryStream);
if (!process.WaitForExit(30000))
{
process.Kill();
return Result<List<string>>.Failure("Hit 'WaitForExit' timeout.");
}
string errorOutput = process.StandardError.ReadToEnd();
if (!string.IsNullOrWhiteSpace(errorOutput))
return Result<List<string>>.Failure(errorOutput);
var outputBuffer = memoryStream.ToArray();
if (outputBuffer.Length == 0)
return Result<List<string>>.Failure("No output received from fd.");
string outputString = Encoding.UTF8.GetString(outputBuffer);
return Result<List<string>>.Success([.. outputString.Split(['\0'], StringSplitOptions.RemoveEmptyEntries)], null);
}
catch (Exception ex)
{
return Result<List<string>>.Failure($"Exception: {ex.Message}");
}
}
private static string BuildFdArguments(string searchDir, string searchTerm, EntryType matchType, bool ignoreCase, bool recursive)
{
var sb = new StringBuilder();
foreach (var option in BaseFdOptions)
sb.Append(option).Append(' ');
sb.Append(ignoreCase ? "--ignore-case " : "--case-sensitive ");
if (matchType == EntryType.File)
sb.Append("--type f ");
else if (matchType == EntryType.Directory)
sb.Append("--type d ");
if (!recursive)
sb.Append("--max-depth 1 ");
sb.Append(searchTerm).Append(' ')
.Append('"').Append(searchDir).Append('"');
return sb.ToString();
}
On a side note, i noticed that the '--unrestricted' flag seems to increase performance by like 3x in my use case. Any insight into that?