fd icon indicating copy to clipboard operation
fd copied to clipboard

'--max-depth 1' & '--exact--depth 1' just parse results?

Open donferris opened this issue 8 months ago • 1 comments

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?

donferris avatar Apr 04 '25 06:04 donferris

I don't know why you are seeing what you do, but fd does skip traversing directories deeper than the max (or exact) depth.

i noticed that the '--unrestricted' flag seems to increase performance by like 3x in my use case. Any insight into that?

Perhaps due to searching for or parsing .gitignore or .ignore files?

tmccombs avatar Apr 07 '25 05:04 tmccombs