Question

Need to search the directory/sub-directories to find a file, would prefer it to stop once it has found one.

Is this a feature built into DirectoryInfo.GetFiles that I am missing, or should I be using something else (self-implemented recursive search)?

Was it helpful?

Solution

Use DirectoryInfo.EnumerateFiles() instead which is lazily returning the files (as opposed to GetFiles which is bringing the full file list into memory first) - you can add FirstOrDefault() to achieve what you want:

var firstTextFile = new DirectoryInfo(someDirectory).EnumerateFiles("*.txt")
                                                    .FirstOrDefault();

From MSDN:

The EnumerateFiles and GetFiles methods differ as follows: When you use EnumerateFiles, you can start enumerating the collection of FileInfo objects before the whole collection is returned; when you use GetFiles, you must wait for the whole array of FileInfo objects to be returned before you can access the array. Therefore, when you are working with many files and directories, EnumerateFiles can be more efficient.

(DirectoryInfo.EnumerateFiles requires .NET 4.0)

OTHER TIPS

The best method to use for pre-.NET 4.0, use FindFirstFile()

    [DllImport("kernel32", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool FindClose(IntPtr hFindFile);

    public void findFile()
    {
        WIN32_FIND_DATA findData;
        var findHandle = FindFirstFile(@"\\?\" + directory + @"\*", out findData);
        FindClose(findHandle);
    }

Requires this struct

    //Struct layout required for FindFirstFile
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }

Have you tried DirectoryInfo.GetFiles([Your Pattern], SearchOption.AllDirectories).First();

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top