.NET에서 디렉토리 크기를 계산하는 가장 좋은 방법은 무엇입니까?


78

디렉터리를 수동으로 탐색하고 C # /. NET에서 크기를 계산하는 다음 루틴을 작성했습니다.


protected static float CalculateFolderSize(string folder)
{
    float folderSize = 0.0f;
    try
    {
        //Checks if the path is valid or not
        if (!Directory.Exists(folder))
            return folderSize;
        else
        {
            try
            {
                foreach (string file in Directory.GetFiles(folder))
                {
                    if (File.Exists(file))
                    {
                        FileInfo finfo = new FileInfo(file);
                        folderSize += finfo.Length;
                    }
                }

                foreach (string dir in Directory.GetDirectories(folder))
                    folderSize += CalculateFolderSize(dir);
            }
            catch (NotSupportedException e)
            {
                Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
            }
        }
    }
    catch (UnauthorizedAccessException e)
    {
        Console.WriteLine("Unable to calculate folder size: {0}", e.Message);
    }
    return folderSize;
}

많은 수의 폴더에 대해이 루틴을 반복적으로 실행하는 응용 프로그램이 있습니다. .NET으로 폴더 크기를 계산하는 더 효율적인 방법이 있는지 궁금합니다. 프레임 워크에서 구체적인 내용을 보지 못했습니다. P / Invoke와 Win32 API를 사용해야합니까? .NET에서 폴더 크기를 계산하는 가장 효율적인 방법은 무엇입니까?

답변:


25

나는 이것에 대해 고칠 수 있지만 디렉토리가 소비하는 공간을 계산하는 Win32 API가 있다고 생각하지 않습니다. 그렇다면 Explorer가 그것을 사용할 것이라고 가정합니다. 탐색기에서 큰 디렉터리의 속성을 얻는 경우 폴더 크기를 제공하는 데 걸리는 시간은 포함 된 파일 / 하위 디렉터리 수에 비례합니다.

당신의 일상은 상당히 깔끔하고 단순 해 보입니다. 디스크에서 사용되는 실제 공간이 아니라 파일 길이의 합계를 계산한다는 점에 유의하십시오. 클러스터, 파일 스트림 등의 끝에서 낭비 된 공간이 사용하는 공간은 무시됩니다.


6
이 방법은 또한 접합, 하드 링크, 압축 및 오프라인 스토리지를 무시합니다.
Anton Tykhyy

10 만 개 이상의 파일이있는 폴더가있을 수 있으므로 EnumerateFiles가 더 바람직 할 수 있습니다. 위에서 언급 한 접합은 무한 재귀 IIRC를 유발할 수 있습니다.
또 다른 메타

1
API가 있습니다. COM (FileSystemObject)입니다. GetFolder ()-Method msdn.microsoft.com/en-us/library/f1xtf7ta(v=vs.84).aspx 및 Size-Property msdn.microsoft.com/en-us/library/2d66skaf(v=vs .84) .aspx
Daniel Fisher lennybacon 2014-08-08

@DanielFisherlennybacon이 어떻게 구현되는지 알고 있습니까? 합니까의 fso.GetFolder().Size루프는 반복적으로 DirSize()수행 혹은 윈도우 폴더 크기를 추적? 어떤 종류의 "크기"를 반환 합니까?
jfs jul.

이 'GetDiskFreeSpaceEx'기능을 사용하지 않는 이유는 무엇입니까? 링크 : msdn.microsoft.com/en-us/library/windows/desktop/…
Ori Nachum

69

아니요, 이는 아래에 포함 된 관련 방법 인 디렉터리 크기를 계산 하는 권장 방법 과 같습니다.

public static long DirSize(DirectoryInfo d) 
{    
    long size = 0;    
    // Add file sizes.
    FileInfo[] fis = d.GetFiles();
    foreach (FileInfo fi in fis) 
    {      
        size += fi.Length;    
    }
    // Add subdirectory sizes.
    DirectoryInfo[] dis = d.GetDirectories();
    foreach (DirectoryInfo di in dis) 
    {
        size += DirSize(di);   
    }
    return size;  
}

루트를 사용하여 다음과 같이 호출합니다.

Console.WriteLine("The size is {0} bytes.", DirSize(new DirectoryInfo(targetFolder));

... targetFolder계산할 폴더 크기는 어디 입니까?


"다음 코드 예제는 디렉토리 크기를 계산하는 방법을 보여줍니다."를 검색하십시오. 위의 예와 동일합니다.
mbrownnyc


1
@ladenedge 업데이트 링크? 그 하나가 v2.0으로 이동합니다 ... 답변 링크가 맞습니다.
kzfabi

BTW : 권장 방법 링크에 더 이상 예제가 포함되지 않습니다. MSDN이 업데이트되어 손실 된 것 같습니다.
kzfabi

4
사용 EnumerateFiles 및 EnumerateDirectories
마우로 Sampietro

34
DirectoryInfo dirInfo = new DirectoryInfo(@strDirPath);
long dirSize = await Task.Run(() => dirInfo.EnumerateFiles( "*", SearchOption.AllDirectories).Sum(file => file.Length));

:이 "UnauthorizedAccess 예외"이 확인 얻는다 stackoverflow.com/questions/8877516/...
아메드 사 브리

@AhmedSabry :이 버그에서 무엇을 이해하고 있습니까?
Trikaldarshiii

이 경로에 대한 권한이 필요합니다
Ahmed Sabry

@AhmedSabry 정확히, 이것이이 1 라이너가 좋은 이유입니다. 모든 권한이 좋으면 좋습니다. 그렇지 않으면 실패하고 특정 사용자 지정 try..catch가 필요하지 않으면 어떤 문제가 있는지 알 수 있습니다.
Ofer Zelig

하위 디렉토리의 전체 경로가 너무 길어질 경우에 발생합니다
user2261015

15
public static long DirSize(DirectoryInfo dir)
{
    return dir.GetFiles().Sum(fi => fi.Length) +
           dir.GetDirectories().Sum(di => DirSize(di));
}

1
이 솔루션에는 NTFS (일명 Junction Points) 및 Unix-SMB 공유에서 재귀 적으로 심볼릭 링크 된 디렉토리에 대한 종료가 없다는 문제가 있습니다.
mbx

1
나는 동의한다. 다른 것은 무엇입니까?
Grozz 2013 년

2
PathTooLongException(이 블로그 게시물 참조 ) 특정 하위 디렉토리 ( UnauthorizedAccessException) 에서 읽을 자격 증명 누락 이 떠 오릅니다. 덜 중요한 문제는 작동 중에 분리 된 이동식 드라이브 (USB 스틱 등)입니다. 여기서 예외 처리는 필수입니다. 로컬에서 0을 반환하고 합계 된 결과가 임의의 값이어야하는 경우 오류를 기록합니다. BTW : 원격 공유에 적용하면 DOS 공격처럼 보일 수 있습니다. 나는 적어도 하나의 다른 경우를 놓쳤다 고 확신합니다 :-)
mbx

이러한 알려진 예외를 처리 할 때 StackOverflowException더 큰 드라이브에 대해 여전히 표시 됩니다.
mbx

2
모든 경우에 던지는 것이 허용되므로 기본 동작이 좋습니다. StackOverflowException재귀 심볼릭 링크없이 도달 할 수 있다고 믿지는 않지만 다루어야 할 유일한 것입니다.
Grozz 2013-09-05

14

진짜 질문은 무엇을 위해 크기를 사용할 계획 입니까?

귀하의 첫 번째 문제가 있다는 것입니다 적어도 "파일 크기"에 대한 정의 :

  • 파일의 처음부터 끝까지 이동하기 위해 건너 뛰어야하는 바이트 수인 "파일 끝"오프셋입니다.
    즉, 파일의 논리적 바이트 수입니다 (사용 측면에서).

  • 실제로 저장되지 않은 첫 번째 바이트의 오프셋과 동일한 "유효한 데이터 길이" 입니다.
    이것은 항상 "파일 끝"보다 작거나 같으며 클러스터 크기의 배수입니다.
    예를 들어 1GB 파일은 1MB의 유효한 데이터 길이를 가질 수 있습니다. Windows에 처음 8MB를 읽도록 요청하면 처음 1MB를 읽고 나머지 데이터가있는 것으로 간주하여 0으로 반환합니다.

  • 파일의 "할당 된 크기". 이것은 항상 "파일 끝"보다 크거나 같습니다.
    OS가 파일에 할당 한 클러스터 수에 클러스터 크기를 곱한 값입니다.
    "파일의 끝"은 "유효한 데이터 길이"보다 큰 경우와는 달리, 초과 바이트되어 있지 OS가 있도록, 파일의 데이터의 일부로 간주 하지 당신이 읽으려고하면 제로와 버퍼를 채우기 파일 끝을 넘어 할당 된 영역.

  • 압축 된 (및 스파 스?) 파일에만 유효한 파일의 "압축 된 크기"입니다. 이 파일에 실제로 할당 된
    볼륨의 클러스터 수를 곱한 클러스터 크기와 같습니다. 비 압축 및 비 희소 파일의 경우 "압축 된 크기"라는 개념이 없습니다. 대신 "할당 된 크기"를 사용합니다.

당신의 두 번째 문제는 같은 "파일"는 것입니다 C:\Foo실제로 여러 가질 수 스트림 데이터를.
이 이름은 기본 스트림을 나타냅니다 . 파일에는 과 같은 대체 스트림 이있을 수 있으며 C:\Foo:Bar그 크기는 탐색기에도 표시되지 않습니다!

귀하의 세 번째 문제는 "파일이"할 수 있다는 것입니다 여러 이름이 ( "하드 링크를").
예를 들어, C:\Windows\notepad.exe그리고 C:\Windows\System32\notepad.exe두 가지 이름 에 대한 동일한 파일. 모든 이름을 사용 하여 파일의 모든 스트림 을 열 수 있습니다 .

번째 문제는 "파일"(또는 디렉토리)이 실제로 파일 (또는 디렉토리)
이 아닐 수도 있다는 것입니다. 다른 파일 ( "기호 링크"또는 "재분석 지점")에 대한 소프트 링크 일 수 있습니다. 또는 디렉토리).
다른 파일은 같은 드라이브에 있지 않을 수도 있습니다. 네트워크상의 무언가를 가리킬 수도 있고 재귀적일 수도 있습니다! 재귀적인 경우 크기는 무한대 여야합니까?

귀하의 다섯 번째는 특정 파일을 만들거나 디렉토리가 "필터"드라이버 있다는 것입니다 보면 그렇지 않은 경우에도 실제 파일이나 디렉토리와 같은가. 예를 들어, Microsoft의 WIM 이미지 파일 (압축 된)은 ImageX라는 도구를 사용하여 폴더에 "마운트"할 수 있으며 재분석 지점이나 링크처럼 보이지 않습니다 . 그것들은 실제로 디렉토리가 아니라는 점을 제외하고는 디렉토리와 똑같습니다. 그리고 "크기"라는 개념이 실제로 의미가 없습니다.

귀하의 여섯 번째 문제는 모든 파일에 메타 데이터를 필요로한다는 것이다.
예를 들어 동일한 파일에 대해 이름이 10 개 있으면 메타 데이터가 더 많이 필요하므로 공간이 필요합니다. 파일 이름이 짧으면 10 개의 이름을 갖는 것이 1 개의 이름을 갖는 것만 큼 저렴할 수 있으며, 길이가 길면 이름이 여러 개인 경우 메타 데이터에 더 많은 디스크 공간 사용할 수 있습니다 . (여러 스트림이있는 같은 이야기 등)
이것도 계산합니까?


2
혼란 스러워요. 이것은 대답이 아니고, (다소 긴) 질문 또는 그 여러 가지입니다.
Ofer Zelig

9
var size = new DirectoryInfo("E:\\").GetDirectorySize();

이 확장 메서드 뒤에있는 코드는 다음과 같습니다.

public static long GetDirectorySize(this System.IO.DirectoryInfo directoryInfo, bool recursive = true)
{
    var startDirectorySize = default(long);
    if (directoryInfo == null || !directoryInfo.Exists)
        return startDirectorySize; //Return 0 while Directory does not exist.

    //Add size of files in the Current Directory to main size.
    foreach (var fileInfo in directoryInfo.GetFiles())
        System.Threading.Interlocked.Add(ref startDirectorySize, fileInfo.Length);

    if (recursive) //Loop on Sub Direcotries in the Current Directory and Calculate it's files size.
        System.Threading.Tasks.Parallel.ForEach(directoryInfo.GetDirectories(), (subDirectory) =>
    System.Threading.Interlocked.Add(ref startDirectorySize, GetDirectorySize(subDirectory, recursive)));

    return startDirectorySize;  //Return full Size of this Directory.
}

1
이 코드는 제 경우 EnumerateFiles ()를 사용하는 어떤 답변보다 빠르게 실행됩니다.
Rm558

6

다음 방법은 재귀 함수보다 더 빠르게 작업을 수행하는 것으로 보입니다.

long size = 0;
DirectoryInfo dir = new DirectoryInfo(folder);
foreach (FileInfo fi in dir.GetFiles("*.*", SearchOption.AllDirectories))
{
   size += fi.Length;
}

간단한 콘솔 애플리케이션 테스트는이 루프가 재귀 함수보다 파일을 더 빠르게 합산하고 동일한 결과를 제공함을 보여줍니다. 이 코드를 단축하기 위해 Sum ()과 같은 LINQ 메서드를 사용하고 싶을 것입니다.


소스 코드와 많은 숨겨진 파일 (svn 디렉토리)이 포함 된 디렉토리를 사용한 테스트에서 결과는 파일 시스템 탐색기에서보고 한 것과 다릅니다.
David Doumèche 2015-10-27

1
언제나처럼 사용하는 "*"대신에 "*.*"확장 파일없이 파일
베른하르트

5

더 빠르게! COM 참조 "Windows 스크립트 호스트 개체 ..."추가

public double GetWSHFolderSize(string Fldr)
    {
        //Reference "Windows Script Host Object Model" on the COM tab.
        IWshRuntimeLibrary.FileSystemObject FSO = new     IWshRuntimeLibrary.FileSystemObject();
        double FldrSize = (double)FSO.GetFolder(Fldr).Size;
        Marshal.FinalReleaseComObject(FSO);
        return FldrSize;
    }
private void button1_Click(object sender, EventArgs e)
        {
            string folderPath = @"C:\Windows";
        Stopwatch sWatch = new Stopwatch();

        sWatch.Start();
        double sizeOfDir = GetWSHFolderSize(folderPath);
        sWatch.Stop();
        MessageBox.Show("Directory size in Bytes : " + sizeOfDir + ", Time: " + sWatch.ElapsedMilliseconds.ToString());
          }

그래 좋아. 그러나 그것은 디스크의 실제 크기가 아닌 파일 크기를 제공하는 것 같습니다 (크기가 18154 바이트이고 디스크 크기가 163840 바이트 인 경우가 있습니다!)
NGI

5

이 솔루션은 매우 잘 작동합니다. 모든 하위 폴더를 수집합니다.

Directory.GetFiles(@"MainFolderPath", "*", SearchOption.AllDirectories).Sum(t => (new FileInfo(t).Length));

4

나는 최근까지 VS2008과 LINQ를 다루어 왔으며이 작고 짧은 방법은 저에게 잘 작동합니다 (예는 VB.NET에 있습니다. 물론 LINQ / .NET FW 3.5+가 필요합니다).

Dim size As Int64 = (From strFile In My.Computer.FileSystem.GetFiles(strFolder, _
              FileIO.SearchOption.SearchAllSubDirectories) _
              Select New System.IO.FileInfo(strFile).Length).Sum()

간단히 말해서 하위 디렉터리를 검색하고 LINQ 구문을 알고 있으면 이해하기 쉽습니다. .GetFiles 함수의 세 번째 매개 변수를 사용하여 특정 파일을 검색하기 위해 와일드 카드를 지정할 수도 있습니다.

저는 C # 전문가는 아니지만 이 방법 으로 C #에 My 네임 스페이스를 추가 할 수 있습니다 .

폴더 크기를 얻는이 방법은 Hao의 link 에 설명 된 방법보다 짧고 현대적 일뿐만 아니라 기본적으로 끝에 설명 된 동일한 loop-of-FileInfo 메서드를 사용한다고 생각합니다.


C # : return Directory.GetFiles (directory, "*", SearchOption.AllDirectories) .Sum (x => (double) (new FileInfo (x) .Length));
thomas nn

3
디렉토리 액세스가 거부되면 실패하고이 예외를 무시할 수 없기 때문에 이상적이지 않습니다.
newman 2013 년

4

이것은 디렉토리의 크기를 계산하는 가장 좋은 방법입니다. 다른 방법 만이 여전히 재귀를 사용하지만 사용하기가 좀 더 쉽고 유연하지 않습니다.

float folderSize = 0.0f;
FileInfo[] files = Directory.GetFiles(folder, "*", SearchOption.AllDirectories);
foreach(FileInfo file in files) folderSize += file.Length;

4
게시 된 코드는 Joe도 말했듯이 작동하지 않습니다. 배열 을 얻으려면이 DirectoryInfo아니라 를 사용해야 합니다. 또한 열거 형은 아닙니다 . DirectoryFileInfoSearchOptionSearchOptions
Tony

당신은 사용할 수 있습니다Array.ConvertAll<string, FileInfo>(Directory.GetFiles(folder, "*", SearchOption.AllDirectories), x => new FileInfo(x));
PJRobot

4

동일한 계산 원칙을 사용하여 @Hao의 답변을 확장했지만 더 풍부한 데이터 반환을 지원하므로 크기, 재귀 적 크기, 디렉터리 수 및 재귀 적 디렉터리 수 (N 수준 깊이)를 얻을 수 있습니다.

public class DiskSizeUtil
{
    /// <summary>
    /// Calculate disk space usage under <paramref name="root"/>.  If <paramref name="levels"/> is provided, 
    /// then return subdirectory disk usages as well, up to <paramref name="levels"/> levels deep.
    /// If levels is not provided or is 0, return a list with a single element representing the
    /// directory specified by <paramref name="root"/>.
    /// </summary>
    /// <returns></returns>
    public static FolderSizeInfo GetDirectorySize(DirectoryInfo root, int levels = 0)
    {
        var currentDirectory = new FolderSizeInfo();

        // Add file sizes.
        FileInfo[] fis = root.GetFiles();
        currentDirectory.Size = 0;
        foreach (FileInfo fi in fis)
        {
            currentDirectory.Size += fi.Length;
        }

        // Add subdirectory sizes.
        DirectoryInfo[] dis = root.GetDirectories();

        currentDirectory.Path = root;
        currentDirectory.SizeWithChildren = currentDirectory.Size;
        currentDirectory.DirectoryCount = dis.Length;
        currentDirectory.DirectoryCountWithChildren = dis.Length;
        currentDirectory.FileCount = fis.Length;
        currentDirectory.FileCountWithChildren = fis.Length;

        if (levels >= 0)
            currentDirectory.Children = new List<FolderSizeInfo>();

        foreach (DirectoryInfo di in dis)
        {
            var dd = GetDirectorySize(di, levels - 1);
            if (levels >= 0)
                currentDirectory.Children.Add(dd);

            currentDirectory.SizeWithChildren += dd.SizeWithChildren;
            currentDirectory.DirectoryCountWithChildren += dd.DirectoryCountWithChildren;
            currentDirectory.FileCountWithChildren += dd.FileCountWithChildren;
        }

        return currentDirectory;
    }

    public class FolderSizeInfo
    {
        public DirectoryInfo Path { get; set; }
        public long SizeWithChildren { get; set; }
        public long Size { get; set; }
        public int DirectoryCount { get; set; }
        public int DirectoryCountWithChildren { get; set; }
        public int FileCount { get; set; }
        public int FileCountWithChildren { get; set; }
        public List<FolderSizeInfo> Children { get; set; }
    }
}

3
public static long GetDirSize(string path)
{
    try
    {
        return Directory.EnumerateFiles(path).Sum(x => new FileInfo(x).Length)  
            +
               Directory.EnumerateDirectories(path).Sum(x => GetDirSize(x));
    }
    catch
    {
        return 0L;
    }
}

2

최고의 알고리즘이되는 한 당신은 아마 그것을 올바르게 가지고있을 것입니다. 재귀 함수를 풀고 자신의 스택을 사용하는 것이 좋습니다 (스택 오버플로는 .Net 2.0+ 앱에서 세상의 끝이라는 것을 기억하십시오. 예외는 IIRC를 잡을 수 없습니다).

가장 중요한 것은 UI의 어떤 형태로든 사용하는 경우 UI 스레드에 업데이트를 알리는 작업자 스레드에 배치하는 것입니다.



2

Trikaldarshi의 한 줄 솔루션에 대한 대안. (FileInfo 객체를 생성 할 필요가 없습니다)

long sizeInBytes = Directory.EnumerateFiles("{path}","*", SearchOption.AllDirectories).Sum(fileInfo => new FileInfo(fileInfo).Length);

변수 fileInfo는 FileInfo가 아닌 문자열 유형입니다.
user425678 nov.

2
Directory.GetFiles(@"C:\Users\AliBayat","*",SearchOption.AllDirectories)
.Select (d => new FileInfo(d))
.Select (d => new { Directory = d.DirectoryName,FileSize = d.Length} )
.ToLookup (d => d.Directory )
.Select (d => new { Directory = d.Key,TotalSizeInMB =Math.Round(d.Select (x =>x.FileSize)
.Sum () /Math.Pow(1024.0,2),2)})
.OrderByDescending (d => d.TotalSizeInMB).ToList();

GetFileswith를 호출 하면 지정된 SearchOption.AllDirectories모든 subdirectories디렉토리에 있는 모든 파일의 전체 이름이 반환 됩니다. OS는 파일 크기를 바이트 단위로 나타냅니다. Length 속성에서 파일 크기를 검색 할 수 있습니다. 1024를 2의 거듭 제곱으로 나누면 파일 크기 (MB)가됩니다. 디렉토리 / 폴더에는 많은 파일이 포함될 수 있으므로 d.Select(x => x.FileSize)메가 바이트 단위로 측정 된 파일 크기 모음을 반환합니다. 마지막 호출 Sum()은 지정된 디렉토리에서 파일의 총 크기 를 찾습니다.

업데이트 : filterMask = " . "는 확장자가없는 파일에서는 작동하지 않습니다 .


1

내가 나온 가장 빠른 방법은 SearchOption.AllDirectories와 함께 EnumerateFiles를 사용하는 것입니다. 이 방법을 사용하면 파일을 살펴보고 크기를 계산하는 동안 UI를 업데이트 할 수도 있습니다. 긴 경로 이름에 대해 FileInfo 또는 DirectoryInfo가 생성되지 않기 때문에 긴 경로 이름은 문제를 일으키지 않습니다. 파일 이름이 길더라도 파일을 열거하는 동안 EnumerateFiles에서 반환 된 FileInfo는 시작 디렉터리 이름이 너무 길지 않은 한 문제를 일으키지 않습니다. UnauthorizedAccess에 여전히 문제가 있습니다.

    private void DirectoryCountEnumTest(string sourceDirName)
    {
        // Get the subdirectories for the specified directory.
        long dataSize = 0;
        long fileCount = 0;
        string prevText = richTextBox1.Text;

        if (Directory.Exists(sourceDirName))
        {
            DirectoryInfo dir = new DirectoryInfo(sourceDirName);
            foreach (FileInfo file in dir.EnumerateFiles("*", SearchOption.AllDirectories))
            {
                fileCount++;
                try
                {
                    dataSize += file.Length;
                    richTextBox1.Text = prevText + ("\nCounting size: " + dataSize.ToString());
                }
                catch (Exception e)
                {
                    richTextBox1.AppendText("\n" + e.Message);
                }
            }
            richTextBox1.AppendText("\n files:" + fileCount.ToString());
        }
    }

1

여기에서이 .NET 핵심 명령 줄 앱은 지정된 경로의 디렉터리 크기를 계산합니다.

https://github.com/garethrbrown/folder-size

핵심 방법은 하위 디렉터리를 재귀 적으로 검사하여 전체 크기를 계산하는 방법입니다.

private static long DirectorySize(SortDirection sortDirection, DirectoryInfo directoryInfo, DirectoryData directoryData)
{
        long directorySizeBytes = 0;

        // Add file sizes for current directory

        FileInfo[] fileInfos = directoryInfo.GetFiles();

        foreach (FileInfo fileInfo in fileInfos)
        {
            directorySizeBytes += fileInfo.Length;
        }

        directoryData.Name = directoryInfo.Name;

        directoryData.SizeBytes += directorySizeBytes;

        // Recursively add subdirectory sizes

        DirectoryInfo[] subDirectories = directoryInfo.GetDirectories();

        foreach (DirectoryInfo di in subDirectories)
        {
            var subDirectoryData = new DirectoryData(sortDirection);

            directoryData.DirectoryDatas.Add(subDirectoryData);

            directorySizeBytes += DirectorySize(sortDirection, di, subDirectoryData);
        }

        directoryData.SizeBytes = directorySizeBytes;

        return directorySizeBytes;
    }
}

1

더 빠를 Microsoft Docs 에서 디렉토리 크기를 계산하는 다중 스레드 예제

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
   public static void Main()
   {
      long totalSize = 0;

      String[] args = Environment.GetCommandLineArgs();
      if (args.Length == 1) {
         Console.WriteLine("There are no command line arguments.");
         return;
      }
      if (! Directory.Exists(args[1])) {
         Console.WriteLine("The directory does not exist.");
         return;
      }

      String[] files = Directory.GetFiles(args[1]);
      Parallel.For(0, files.Length,
                   index => { FileInfo fi = new FileInfo(files[index]);
                              long size = fi.Length;
                              Interlocked.Add(ref totalSize, size);
                   } );
      Console.WriteLine("Directory '{0}':", args[1]);
      Console.WriteLine("{0:N0} files, {1:N0} bytes", files.Length, totalSize);
   }
}
// The example displaysoutput like the following:
//       Directory 'c:\windows\':
//       32 files, 6,587,222 bytes

이 예에서는 현재 폴더의 파일 만 계산하므로 모든 파일을 재귀 적으로 계산하려는 경우

String[] files = Directory.GetFiles(args[1]);

...에

String[] files = Directory.GetFiles(args[1], "*", SearchOption.AllDirectories);


0

샘플을 변경하려고합니다 (Alexandre Pepin과 hao의 답변)

그대로

    private long GetDirectorySize(string dirPath)
    {
        if (Directory.Exists(dirPath) == false)
        {
            return 0;
        }

        DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

        long size = 0;

        // Add file sizes.
        FileInfo[] fis = dirInfo.GetFiles();
        foreach (FileInfo fi in fis)
        {
            size += fi.Length;
        }

        // Add subdirectory sizes.
        DirectoryInfo[] dis = dirInfo.GetDirectories();
        foreach (DirectoryInfo di in dis)
        {
            size += GetDirectorySize(di.FullName);
        }

        return size;
    }

되려고

    private long GetDirectorySize2(string dirPath)
    {
        if (Directory.Exists(dirPath) == false)
        {
            return 0;
        }

        DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

        long size = 0;

        // Add file sizes.
        IEnumerable<FileInfo> fis = dirInfo.EnumerateFiles("*.*", SearchOption.AllDirectories);
        foreach (FileInfo fi in fis)
        {
            size += fi.Length;
        }

        return size;
    }

마지막으로 결과를 확인할 수 있습니다

        // ---------------------------------------------
        // size of directory
        using System.IO;

        string log1Path = @"D:\SampleDirPath1";
        string log2Path = @"D:\SampleDirPath2";
        string log1DirName = Path.GetDirectoryName(log1Path);
        string log2DirName = Path.GetDirectoryName(log2Path);
        long log1Size = GetDirectorySize(log1Path);
        long log2Size = GetDirectorySize(log2Path);
        long log1Size2 = GetDirectorySize2(log1Path);
        long log2Size2 = GetDirectorySize2(log2Path);

        Console.WriteLine($@"{log1DirName} Size: {SizeSuffix(log1Size)}, {SizeSuffix(log1Size2)}
        {log2DirName} Size: {SizeSuffix(log2Size)}, {SizeSuffix(log2Size2)}");

이것이 SizeSuffix 함수입니다.

    private static readonly string[] SizeSuffixes =
               { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };

    /// <summary>
    /// Size Display
    /// </summary>
    /// <param name="value">bytes 數值</param>
    /// <param name="decimalPlaces">小數位數</param>
    /// <returns></returns>
    public static string SizeSuffix(Int64 value, int decimalPlaces = 2)
    {
        if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); }
        if (value < 0) { return "-" + SizeSuffix(-value); }
        if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); }

        // mag is 0 for bytes, 1 for KB, 2, for MB, etc.
        int mag = (int)Math.Log(value, 1024);

        // 1L << (mag * 10) == 2 ^ (10 * mag) 
        // [i.e. the number of bytes in the unit corresponding to mag]
        decimal adjustedSize = (decimal)value / (1L << (mag * 10));

        // make adjustment when the value is large enough that
        // it would round up to 1000 or more
        if (Math.Round(adjustedSize, decimalPlaces) >= 1000)
        {
            mag += 1;
            adjustedSize /= 1024;
        }

        return string.Format("{0:n" + decimalPlaces + "} {1}",
            adjustedSize,
            SizeSuffixes[mag]);
    }

-3

나는 이것이 .net 솔루션이 아니라는 것을 알고 있지만 어쨌든 여기에 있습니다. Windows 10이 있고 더 빠른 솔루션을 원하는 사람들에게 유용 할 수 있습니다. 예를 들어이 명령을 명령 프롬프트에서 실행하거나 다음을 눌러 실행하는 경우 winKey + R:

bash -c "du -sh /mnt/c/Users/; sleep 5"    

그만큼 sleep 5 당신이 결과를 볼 시간이되도록하고 창은 닫히고하지 않습니다

표시되는 내 컴퓨터에서 :

여기에 이미지 설명 입력

마지막에 85G (85 기가 바이트)가 어떻게 표시되는지 확인하십시오. .Net으로하는 것에 비해 저녁 식사가 빠릅니다. 크기를 더 정확하게보고 싶다면h 사람이 읽을 수 .

따라서 Processes.Start("bash",... arguments)정확한 코드는 아니지만 아이디어를 얻을 수 있습니다.

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