let find ?(follow = Skip) tst fln exec accu =
    let ctest = compile_filter (And(tst,Not(Or(Is_parent_dir,Is_current_dir))))
    in
    let cdir  = compile_filter (And(Is_dir,Not(Or(Is_parent_dir,Is_current_dir))))
    in
    let clink = fun fln ->
      if test Is_link fln then
        match follow with
          Follow -> true
        | Skip   -> false
        | SkipInform f -> f fln; false
        | AskFollow f -> f fln
      else
        true    
    in
    let rec find_dir (already_read,accu) fln =
      let _ = dbug_print ("Entering dir : "^(fln))
      in
      let newly_read = prevent_recursion already_read (make_absolute (pwd ()) (readlink fln))
      in
      let _ = dbug_print "Recursion test passed"
      in
      let dir_content = ls fln
      in
      let _ = dbug_print_list "Directory listing" dir_content
      in
      let new_accu = List.fold_left exec accu (List.filter ctest dir_content)
      in
      let directories = List.filter clink (List.filter cdir dir_content)
      in
      if directories = [] then
        (newly_read,new_accu)
      else
        List.fold_left find_dir (newly_read,new_accu) directories
    in
    let find_simple (already_read,accu) fln =
      let new_accu = 
        if ctest fln then
          exec accu fln
        else
          accu
      in
      if test Is_dir fln then
        find_dir (already_read,new_accu) fln
      else
        (already_read,new_accu)
    in
    snd(find_simple (SetFilename.empty,accu) fln)