디렉토리 + 하위 디렉토리의 모든 파일 및 디렉토리 나열


109

디렉토리 및 해당 디렉토리의 하위 디렉토리에 포함 된 모든 파일과 디렉토리를 나열하고 싶습니다. 디렉토리로 C : \를 선택하면 프로그램은 액세스 권한이있는 하드 드라이브에있는 모든 파일과 폴더의 모든 이름을 가져옵니다.

목록은 다음과 같을 수 있습니다.

fd \ 1.txt
fd \ 2.txt
fd \ a \
fd \ b \
fd \ a \ 1.txt
fd \ a \ 2.txt
fd \ a \ a \
fd \ a \ b \
fd \ b \ 1.txt
fd \ b \ 2.txt
fd \ b \ a
fd \ b \ b
fd \ a \ a \ 1.txt
fd \ a \ a \ a \
fd \ a \ b \ 1.txt
fd \ a \ b \ a
fd \ b \ a \ 1.txt
fd \ b \ a \ a \
fd \ b \ b \ 1.txt
fd \ b \ b \ a

도움이 될 수있는 클래스메서드에 대한 System.IO 네임 스페이스를 찾아 보십시오.
Lucero

이 질문을 확인하고 패턴과 일치하는 부분을 삭제하십시오.
dasblinkenlight 2012 년

답변:


192
string[] allfiles = Directory.GetFiles("path/to/dir", "*.*", SearchOption.AllDirectories);

*.*파일과 일치시킬 패턴은 어디에 있습니까?

디렉토리도 필요하면 다음과 같이 갈 수 있습니다.

 foreach (var file in allfiles){
     FileInfo info = new FileInfo(file);
 // Do something with the Folder or just add them to a list via nameoflist.add();
 }

1
정말 안 통 하네 ... Lsit<>수업? GetFiles는 무엇을 반환합니까? 또한 요청 된 디렉토리 이름은 어떻습니까?
Lucero

1
GetFiles메서드는 문자열 배열을 반환합니다.
Guffa

actualy ... 당신이 바로 ... 내가 잘못의 작은 2 일 전 abaout Qt는 학습이었다 있어요된다
루슬란 F.

이것은 작동 할 수 있지만 종종 UnauthorizedAccessException으로 실패합니다. 액세스 할 수있는 디렉토리 만 검색하는 방법은 무엇입니까?
derp_in_mouth

그것은 당신의 시스템에서이 응용 프로그램에 충분한 권한을 가지고 있지 않았 음을 의미합니다
루슬란 F.

50

Directory.GetFileSystemEntries.NET 4.0+에 존재하며 파일과 디렉토리를 모두 반환합니다. 그렇게 부르십시오.

string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);

액세스 권한이없는 하위 디렉터리의 내용을 나열하려는 시도 (UnauthorizedAccessException)에는 대처할 수 없지만 필요에 따라 충분할 수 있습니다.


3
이것은 여기에서 가장 좋은 대답입니다. 한 줄의 코드로 모든 파일과 폴더를 가져 오지만 다른 코드는 수행하지 않습니다.
Steve Smith

15

GetDirectoriesGetFiles메서드를 사용하여 폴더와 파일을 가져옵니다.

를 사용하여 하위 폴더의 폴더와 파일도 가져옵니다.SearchOption AllDirectories


하위 문자열 을 사용 하여 이름의 왼쪽 부분을 잘라냅니다. :)
Lucero

@Lucero 어떻게 그리고 왜 그렇게 하시겠습니까? Path보다 안정적인 방법을 제공합니다.
Gusdor 2017 년

@Gusdor Path경로의 고정 된 왼쪽 부분을 제거하기 위해를 사용하여 더 적합한 방법을 자유롭게 제안 하십시오 (예 : 주어진 예에서`C :`).
Lucero

@Lucero 내 의견이 제대로 표현되지 않았습니다. 'Use substring' 은 나에게 많은 것을 알려주지 않았고 좋은 솔루션을 도출하기 위해 linqpad에 갇혀 야했습니다. 예를 들어, 매개 변수는 무엇입니까? 당신이 할 것입니까 path.SubString(2)순진 드라이브 문자와 콜론을 제거하려면? 디렉토리가 네트워크 공유이면 어떻게됩니까? Path이 분야에서 많은 혜택을 제공 할 수 있기 때문에 신뢰할 수있는 방법으로 제안 합니다. 이 경우 filePath.Substring(Path.GetPathRoot(filePath).Length). 예, 가장 간결한 부분 문자열을 사용합니다.
Gusdor 2017 년

10
public static void DirectorySearch(string dir)
{
    try
    {
        foreach (string f in Directory.GetFiles(dir))
        {
            Console.WriteLine(Path.GetFileName(f));
        }
        foreach (string d in Directory.GetDirectories(dir))
        {
            Console.WriteLine(Path.GetFileName(d));
            DirectorySearch(d);
        }
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

3
코드가 수행하는 작업에 대한 약간의 설명을 추가 할 수 있다면 답변이 향상 될 것입니다.
Alex

디렉토리를 반복적으로 살펴보고 파일 이름이나 디렉토리 이름을 인쇄합니다. 모든 내부 디렉토리에 대해 동일한 함수를 호출합니다. 자세한 정보 : stackoverflow.com/questions/929276/…
I. Step

3

GetFiles방법은 파일 목록을 반환하지만 디렉토리는 반환하지 않습니다. 질문의 목록은 결과에 폴더도 포함되어야한다는 메시지를 표시합니다. 더 많은 사용자 정의 목록을 원하면 호출 GetFilesGetDirectories재귀 적으로 시도 할 수 있습니다 . 이 시도:

List<string> AllFiles = new List<string>();
void ParsePath(string path)
{
    string[] SubDirs = Directory.GetDirectories(path);
    AllFiles.AddRange(SubDirs);
    AllFiles.AddRange(Directory.GetFiles(path));
    foreach (string subdir in SubDirs)
        ParsePath(subdir);
}

팁 : 특정 속성을 확인해야하는 경우 FileInfoDirectoryInfo클래스를 사용할 수 있습니다 .


1

핸들을 반환하는 FindFirstFile을 사용하고 FindNextFile을 호출하는 함수를 재귀 적으로 계산할 수 있습니다. 참조 된 구조가 alternativeName, lastTmeCreated, modified, attributes 등과 같은 다양한 데이터로 채워지기 때문에 이것은 좋은 접근입니다.

그러나 .net 프레임 워크를 사용하면 관리되지 않는 영역으로 들어가야합니다.


1

최대 lvl이 디렉토리에 내려 가고 폴더를 제외하는 옵션이있는 일부 개선 된 버전 :

using System;
using System.IO;

class MainClass {
  public static void Main (string[] args) {

    var dir = @"C:\directory\to\print";
    PrintDirectoryTree(dir, 2, new string[] {"folder3"});
  }


  public static void PrintDirectoryTree(string directory, int lvl, string[] excludedFolders = null, string lvlSeperator = "")
  {
    excludedFolders = excludedFolders ?? new string[0];

    foreach (string f in Directory.GetFiles(directory))
    {
        Console.WriteLine(lvlSeperator+Path.GetFileName(f));
    } 

    foreach (string d in Directory.GetDirectories(directory))
    {
        Console.WriteLine(lvlSeperator + "-" + Path.GetFileName(d));

        if(lvl > 0 && Array.IndexOf(excludedFolders, Path.GetFileName(d)) < 0)
        {
          PrintDirectoryTree(d, lvl-1, excludedFolders, lvlSeperator+"  ");
        }
    }
  }
}

입력 디렉토리 :

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
      file6.txt
  -folder3
    file3.txt
  -folder4
    file4.txt
    file5.txt

함수 출력 (폴더 5의 내용은 lvl 제한으로 인해 제외되고 folder3의 내용은 excludedFolders 배열에 있으므로 제외됨) :

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
  -folder3
  -folder4
    file4.txt
    file5.txt

0

디렉터리 트리 내부의 하위 폴더에 액세스 할 수없는 경우 Directory.GetFiles는 수신 문자열 []에 null 값이 발생하는 예외를 중지하고 throw합니다.

여기,이 대답을보십시오 참조하십시오 https://stackoverflow.com/a/38959208/6310707

루프 내에서 예외를 관리하고 전체 폴더가 탐색 될 때까지 계속 작업합니다.


0

논리적이고 정돈 된 방법 :

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace DirLister
{
class Program
{
    public static void Main(string[] args)
    {
        //with reflection I get the directory from where this program is running, thus listing all files from there and all subdirectories
        string[] st = FindFileDir(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
        using ( StreamWriter sw = new StreamWriter("listing.txt", false ) )
        {
            foreach(string s in st)
            {
                //I write what I found in a text file
                sw.WriteLine(s);
            }
        }
    }

    private static string[] FindFileDir(string beginpath)
    {
        List<string> findlist = new List<string>();

        /* I begin a recursion, following the order:
         * - Insert all the files in the current directory with the recursion
         * - Insert all subdirectories in the list and rebegin the recursion from there until the end
         */
        RecurseFind( beginpath, findlist );

        return findlist.ToArray();
    }

    private static void RecurseFind( string path, List<string> list )
    {
        string[] fl = Directory.GetFiles(path);
        string[] dl = Directory.GetDirectories(path);
        if ( fl.Length>0 || dl.Length>0 )
        {
            //I begin with the files, and store all of them in the list
            foreach(string s in fl)
                list.Add(s);
            //I then add the directory and recurse that directory, the process will repeat until there are no more files and directories to recurse
            foreach(string s in dl)
            {
                list.Add(s);
                RecurseFind(s, list);
            }
        }
    }
}
}

설명이나 인라인 주석을 제공해 주시겠습니까? 코드의 기능은 무엇입니까?
MarthyM

물론, 그 일을하지만 자기 설명을해야한다, 모든 통해 디렉토리와 파일을 재귀 반복하는 간단한이다
샤샤

0

다음 예는 가장 빠른 예외를 처리하는 디렉토리 트리에서 파일과 하위 폴더를 나열 (병렬화되지 않은) 방법입니다. SearchOption.AllDirectories를 사용하여 Directory.EnumerateDirectories를 사용하여 모든 디렉토리를 열거하는 것이 더 빠르지 만 UnauthorizedAccessException 또는 PathTooLongException이 발생하면이 메서드가 실패합니다.

LIFO (last in first out) 스택이고 재귀를 사용하지 않는 일반 스택 컬렉션 유형을 사용합니다. 에서 https://msdn.microsoft.com/en-us/library/bb513869.aspx , 모든 하위 디렉토리 및 파일을 열거하고 그 예외를 효과적으로 처리 할 수 있습니다.

    public class StackBasedIteration
{
    static void Main(string[] args)
    {
        // Specify the starting folder on the command line, or in 
        // Visual Studio in the Project > Properties > Debug pane.
        TraverseTree(args[0]);

        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    public static void TraverseTree(string root)
    {
        // Data structure to hold names of subfolders to be
        // examined for files.
        Stack<string> dirs = new Stack<string>(20);

        if (!System.IO.Directory.Exists(root))
        {
            throw new ArgumentException();
        }
        dirs.Push(root);

        while (dirs.Count > 0)
        {
            string currentDir = dirs.Pop();
            string[] subDirs;
            try
            {
                subDirs = System.IO.Directory.EnumerateDirectories(currentDir); //TopDirectoryOnly
            }
            // An UnauthorizedAccessException exception will be thrown if we do not have
            // discovery permission on a folder or file. It may or may not be acceptable 
            // to ignore the exception and continue enumerating the remaining files and 
            // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
            // will be raised. This will happen if currentDir has been deleted by
            // another application or thread after our call to Directory.Exists. The 
            // choice of which exceptions to catch depends entirely on the specific task 
            // you are intending to perform and also on how much you know with certainty 
            // about the systems on which this code will run.
            catch (UnauthorizedAccessException e)
            {                    
                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            string[] files = null;
            try
            {
                files = System.IO.Directory.EnumerateFiles(currentDir);
            }

            catch (UnauthorizedAccessException e)
            {

                Console.WriteLine(e.Message);
                continue;
            }

            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            // Perform the required action on each file here.
            // Modify this block to perform your required task.
            foreach (string file in files)
            {
                try
                {
                    // Perform whatever action is required in your scenario.
                    System.IO.FileInfo fi = new System.IO.FileInfo(file);
                    Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
                }
                catch (System.IO.FileNotFoundException e)
                {
                    // If file was deleted by a separate application
                    //  or thread since the call to TraverseTree()
                    // then just continue.
                    Console.WriteLine(e.Message);
                    continue;
                }
                catch (UnauthorizedAccessException e)
                {                    
                    Console.WriteLine(e.Message);
                    continue;
                }
            }

            // Push the subdirectories onto the stack for traversal.
            // This could also be done before handing the files.
            foreach (string str in subDirs)
                dirs.Push(str);
        }
    }
}

대용량 파일 및 디렉토리에 작업 을 사용 하십니까?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx 는 스택 컬렉션을 사용하는 위 솔루션의 병렬 스레딩 버전입니다.
Markus

0

하나는 종료 용이고 다른 하나는 시작 용으로 두 개의 버튼이있는 양식에 다음 코드를 사용합니다. 폴더 브라우저 대화 상자 및 파일 저장 대화 상자. 코드는 아래에 나열되어 있으며 내 시스템 Windows10 (64)에서 작동합니다.

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Directory_List
{

    public partial class Form1 : Form
    {
        public string MyPath = "";
        public string MyFileName = "";
        public string str = "";

        public Form1()
        {
            InitializeComponent();
        }    
        private void cmdQuit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }    
        private void cmdGetDirectory_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();
            MyPath = folderBrowserDialog1.SelectedPath;    
            saveFileDialog1.ShowDialog();
            MyFileName = saveFileDialog1.FileName;    
            str = "Folder = " + MyPath + "\r\n\r\n\r\n";    
            DirectorySearch(MyPath);    
            var result = MessageBox.Show("Directory saved to Disk!", "", MessageBoxButtons.OK);
                Application.Exit();    
        }    
        public void DirectorySearch(string dir)
        {
                try
            {
                foreach (string f in Directory.GetFiles(dir))
                {
                    str = str + dir + "\\" + (Path.GetFileName(f)) + "\r\n";
                }    
                foreach (string d in Directory.GetDirectories(dir, "*"))
                {

                    DirectorySearch(d);
                }
                        System.IO.File.WriteAllText(MyFileName, str);

            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

0

이것으로 콘솔을 실행할 때 실행하고 하위 폴더를 선택할 수 있습니다.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using data.Patcher; // The patcher XML
namespace PatchBuilder
{
class Program
{
    static void Main(string[] args)
    {
        string patchDir;
        if (args.Length == 0)
        {
            Console.WriteLine("Give the patch directory in argument");
            patchDir = Console.ReadLine();
        }
        else
        {
            patchDir = args[0];
        }

        if (File.Exists(Path.Combine(patchDir, "patch.xml")))
            File.Delete(Path.Combine(patchDir, "patch.xml"));

        var files = Directory.EnumerateFiles(patchDir, "*", SearchOption.AllDirectories).OrderBy(p => p).ToList();

        foreach (var file in files.Where(file => file.StartsWith("patch\\Resources")).ToArray())
        {
            files.Remove(file);
            files.Add(file);
        }

        var tasks = new List<MetaFileEntry>();
        using (var md5Hasher = MD5.Create())
        {
            for (int i = 0; i < files.Count; i++)
            {
                var file = files[i];

                if ((File.GetAttributes(file) & FileAttributes.Hidden) != 0)
                    continue;

                var content = File.ReadAllBytes(file);
                var md5Hasher2 = MD5.Create();

                var task =
                    new MetaFileEntry
                    {
                        LocalURL = GetRelativePath(file, patchDir + "\\"),
                        RelativeURL = GetRelativePath(file, patchDir + "\\"),
                        FileMD5 = Convert.ToBase64String(md5Hasher2.ComputeHash(content)),
                        FileSize = content.Length,
                    };

                md5Hasher2.Dispose();

                var pathBytes = Encoding.UTF8.GetBytes(task.LocalURL.ToLower());
                md5Hasher.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
                if (i == files.Count - 1)
                    md5Hasher.TransformFinalBlock(content, 0, content.Length);
                else
                    md5Hasher.TransformBlock(content, 0, content.Length, content, 0);

                tasks.Add(task);
                Console.WriteLine(@"Add " + task.RelativeURL);
            }

            var patch = new MetaFile
            {
                Tasks = tasks.ToArray(),
                FolderChecksum = BitConverter.ToString(md5Hasher.Hash).Replace("-", "").ToLower(),
            };


            //XmlUtils.Serialize(Path.Combine(patchDir, "patch.xml"), patch);
            Console.WriteLine(@"Created Patch in {0} !", Path.Combine(patchDir, "patch.xml"));
        }

        Console.Read();
    }

    static string GetRelativePath(string fullPath, string relativeTo)
    {
        var foldersSplitted = fullPath.Split(new[] { relativeTo.Replace("/", "\\").Replace("\\\\", "\\") }, StringSplitOptions.RemoveEmptyEntries); // cut the source path and the "rest" of the path

        return foldersSplitted.Length > 0 ? foldersSplitted.Last() : ""; // return the "rest"
    }
}
}

그리고 이것은 XML 내보내기를위한 patchar입니다.

using System.Xml.Serialization;

namespace data.Patcher
{
    public class MetaFile
    {

        [XmlArray("Tasks")]
        public MetaFileEntry[] Tasks
        {
            get;
            set;
        }

        [XmlAttribute("checksum")]
        public string FolderChecksum
        {
            get;
            set;
        }
    }
}

-1
using System.IO;
using System.Text;
string[] filePaths = Directory.GetFiles(@"path", "*.*", SearchOption.AllDirectories);

귀하의 답변은 기존의 최고 투표 답변에 새로운 내용을 추가하지 않습니다.
기본 로케일

1
이것은 (질문이 지정한대로) 어떤 디렉토리도 반환하지 않고 실제 파일 만 반환하기 때문에 잘못되었습니다.
Alastair Maw

-1

조금 간단하고 느리지 만 작동합니다 !! 파일 경로를 제공하지 않으면 기본적으로 "fixPath"를 사용하십시오. 이것은 단지 예일뿐입니다 .... 원하는 올바른 fileType을 검색 할 수 있습니다. "temporaryFileList가 검색된 파일 목록이기 때문에 목록 이름을 선택할 때 실수했습니다. 그러니 계속하십시오 .... 그리고 "errorList"는 스스로를 말합니다.

 static public void Search(string path, string fileType, List<string> temporaryFileList, List<string> errorList)
    {

        List<string> temporaryDirectories = new List<string>();

        //string fix = @"C:\Users\" + Environment.UserName + @"\";
        string fix = @"C:\";
        string folders = "";
        //Alap útvonal megadása 
        if (path.Length != 0)
        { folders = path; }
        else { path = fix; }

        int j = 0;
        int equals = 0;
        bool end = true;

        do
        {

            equals = j;
            int k = 0;

            try
            {

                int foldersNumber = 
                Directory.GetDirectories(folders).Count();
                int fileNumber = Directory.GetFiles(folders).Count();

                if ((foldersNumber != 0 || fileNumber != 0) && equals == j)
                {

                    for (int i = k; k < 
                    Directory.GetDirectories(folders).Length;)
                    {

             temporaryDirectories.Add(Directory.GetDirectories(folders)[k]);
                        k++;
                    }

                    if (temporaryDirectories.Count == j)
                    {
                        end = false;
                        break;
                    }
                    foreach (string files in Directory.GetFiles(folders))
                    {
                        if (files != string.Empty)
                        {
                            if (fileType.Length == 0)
                            {
                                temporaryDirectories.Add(files);
                            }
                            else
                            {

                                if (files.Contains(fileType))
                                {
                                    temporaryDirectories.Add(files);

                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                }

                equals++;

                for (int i = j; i < temporaryDirectories.Count;)
                {
                    folders = temporaryDirectories[i];
                    j++;
                    break;
                }

            }
            catch (Exception ex)
            {
                errorList.Add(folders);

                for (int i = j; i < temporaryDirectories.Count;)
                {
                    folders = temporaryDirectories[i];
                    j++;
                    break;
                }
            }
        } while (end);
    }

-1

문자열 목록 만들기

    public static List<string> HTMLFiles = new List<string>();

 private void Form1_Load(object sender, EventArgs e)
        {

     HTMLFiles.AddRange(Directory.GetFiles(@"C:\DataBase", "*.txt"));
            foreach (var item in HTMLFiles)
            {
                MessageBox.Show(item);
            }

}

이것은 하위 디렉토리를 가져 오지 않습니다.
TidyDev

-1

dir / s / b .> results.txt

/ s = 하위 폴더 / b = 결과 곰

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.