Jeśli dasz radę, uniknij tego bałaganu, chwytając narzędzie Sysinternals du i uruchamiając du -v <directoryname>. Dane wyjściowe będą kilobajtami. -vOpcja środków wyjściowych rozmiar wszystkich podkatalogów.
W obecnym skrypcie problemem wydaje się dodawanie tekstu w pętli. Łatwym obejściem jest wyjście do okna wiersza poleceń, na przykład:
echo %%q
echo !xsize!
a po uruchomieniu pliku wsadowego wysłano jego wynik do pliku tekstowego: test.bat > size.txt
Szybka wskazówka: pierwszy bit można uprościć za pomocą:
for /f "tokens=*" %%q in ('dir /a:d /s /b') do (
cd "%%q"
...
echo !xsize!
)
Zasadniczo, to zastąpienie użycia findz /a:dopcją (lista katalogów tylko) i /b(używaj gołego formatu, bez nagłówka lub podsumowania). Spowoduje to również usunięcie pliku tymczasowego.
Zmodyfikowana wersja do pracy na folderach z wykrzyknikami w nazwie. Korzystając z odpowiedzi Scotta. Zobacz komentarze poniżej.
Uwaga: REMoznacza to komentarz.
@echo off
REM clear the file
type NUL > size.txt
for /f "tokens=*" %%q IN ('dir /a:d /s /b') do (
echo %%q >> size.txt
REM Run :getsize, passing "%%q" including quotes as the first parameter
call :getsize "%%q" >> size.txt
)
REM go to the end of the file, i.e. exit
goto :eof
:getsize
REM %1 is the first parameter. It should already be quoted.
for /f "tokens=*" %%h IN ('"dir /s /-c /a %1 | find "bytes" | find /v "free""') do set xsummary=%%h
for /f "tokens=1,2 delims=)" %%a in ("%xsummary%") do set xsize=%%b
set xsize=%xsize:bytes=%
set xsize=%xsize: =%
echo %xsize%
goto :eof
Alternatywą jest użycie programu PowerShell:
Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | %{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_} | Sort-Object DirSize -Descending | Select-Object -First 10 FullName,DirSize | Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';
Jest to zbyt skomplikowane, aby było możliwie jak najbardziej kompletne - ponadto większość z tych poleceń ma krótsze aliasy; to jest po prostu bardziej czytelne. A jeśli podzielisz niektóre sekcje na funkcje / własną linię, stanie się to znacznie bardziej czytelne i być może krótsze.
Rozbuduj to:
Get-ChildItem -Recurse
Rekurencyjnie wyświetl wszystkie podkatalogi i pliki
?{ $_.PSIsContainer }
Filtruj, aby zachować tylko katalogi ( ?jest to alias Where-Object). $_odnosi się do obiektów przesłanych do tego potoku - ponieważ Get-ChildItemprzekazuje listę / tablicę obiektów, przetwarza je pojedynczo.
%{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_}
Oblicz rozmiar każdego katalogu ( %jest to alias Foreach-Object, więc uruchom to, co znajduje się pomiędzy { }poszczególnymi obiektami. Każdy obiekt jest katalogiem, jak w poprzednich częściach).
Rozbuduj to:
$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0;
Średnik ( ;) oznacza koniec linii / instrukcji i nie przekazuje danych wyjściowych, w przeciwieństwie do potoku ( |). Ten konkretny bit nie ma danych wyjściowych, a jedynie dodaje DirSizewłaściwość do obiektu katalogu i inicjuje ją na 0. Jest to wykonywane w celu łatwiejszego filtrowania i późniejszego uporządkowania danych wyjściowych.
$_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum;
Ustaw DirSizena Sumwłaściwość wyniku tego polecenia. $()oznacza wykonanie tego, co jest w nawiasach i zastąpienie tego w.
Rozbuduj to:
Get-ChildItem -Recurse $_.Fullname
Dostać całą zawartość katalogu bieżącego obiektu ( $_, Fullnamepo prostu oznacza pełną ścieżkę). -Recurseoznacza również policzenie zawartości podkatalogów.
?{ -not $_.PSIsContainer }
Filtruj, aby zachować tylko pliki. Katalogi mają Lengthwłaściwość 0, więc musimy użyć sumowania plików w środku - zasadniczo tego, co robi twój skrypt wsadowy, z tym wyjątkiem, że mamy do czynienia z rzeczywistymi liczbami, obiektami i właściwościami zamiast chwytania „liczby” jako tekstu find.
Measure-Object -Sum -Property Length
Oblicz sumę wszystkich Lengthprzekazanych do niego właściwości. Zwraca obiekt zawierający właściwość Sum, która jest używana powyżej ( .Sum)
$_
Zasadniczo echoobiekt przenosi go do następnej sekcji. Teraz ma DirSizewłaściwość.
Sort-Object DirSize -Descending
Sortuj malejąco według DirSize
Select-Object -First 10 FullName,DirSize
Wyprowadzaj tylko pierwsze 10, a tylko nazwę i rozmiar
Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';
Dane wyjściowe do sizes.txt. Format-TableI Out-Stringbity są do zapobiegania obcinania do konsoli szerokości okien (zazwyczaj 80 znaków). 4096 powinien zawierać więcej niż wystarczającą liczbę znaków dla dowolnej ścieżki systemu Windows i rozmiaru katalogu, biorąc pod uwagę, że ścieżka systemu Windows jest zwykle ograniczona do 255 znaków (IIRC). AutoSizeOznacza po prostu zrobić to możliwie jak najkrótszy bez obcinania, zamiast wyściółka z całym mnóstwem spacji aby dopasować 4096 znaków.
I polecenie jako jeden liniowiec do uruchomienia cmd.exe(możesz uruchomić powyższą wersję w programie PowerShell):
powershell -c "Get-ChildItem -Recurse | ?{ $_.PSIsContainer } | %{$_ | Add-Member -MemberType NoteProperty -Name DirSize -Value 0; $_.DirSize = $(Get-ChildItem -Recurse $_.Fullname | ?{ -not $_.PSIsContainer } | Measure-Object -Sum -Property Length).Sum; $_} | Sort-Object DirSize -Descending | Select-Object -First 10 FullName,DirSize | Format-Table -AutoSize | Out-String -Width 4096 | Out-File 'sizes.txt';"