W poniższym kodzie muszę wziąć ścieżkę i rozmiar folderu i podfolderów do pliku. Ale gdy pętla działa po raz drugi, ścieżka i rozmiar nie są drukowane do pliku. size.txt zawiera tylko ścieżkę i rozmiar pierwszego folderu. Proszę, niech ktoś mi pomoże.
@echo off
SETLOCAL EnableDelayedExpansion
SET xsummary=
SET xsize=
for /f "tokens=1,2 delims=C" %%i IN ('"dir /s /-c /a | find "Directory""') do (echo C%%j >> abcd.txt)
for /f "tokens=*" %%q IN (abcd.txt) do (
cd "%%q"
For /F "tokens=*" %%h IN ('"dir /s /-c /a | 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.%%q >> size.txt
echo.!xsize! >> size.txt
)
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.-v
Opcja ś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:
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ą:
Zasadniczo, to zastąpienie użycia
find
z/a:d
opcją (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:
REM
oznacza to komentarz.Alternatywą jest użycie programu PowerShell:
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 aliasWhere-Object
).$_
odnosi się do obiektów przesłanych do tego potoku - ponieważGet-ChildItem
przekazuje 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 aliasForeach-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 dodajeDirSize
wł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
DirSize
naSum
wł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 (
$_
,Fullname
po prostu oznacza pełną ścieżkę).-Recurse
oznacza również policzenie zawartości podkatalogów.?{ -not $_.PSIsContainer }
Filtruj, aby zachować tylko pliki. Katalogi mają
Length
wł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 tekstufind
.Measure-Object -Sum -Property Length
Oblicz sumę wszystkich
Length
przekazanych do niego właściwości. Zwraca obiekt zawierający właściwośćSum
, która jest używana powyżej (.Sum
)$_
Zasadniczo
echo
obiekt przenosi go do następnej sekcji. Teraz maDirSize
wł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-Table
IOut-String
bity 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).AutoSize
Oznacza 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):źródło
dir
polecenia - twój oryginał zrobiłby to samo. Problem jest z powoduEnableDelayedExpansion
.cmd
Najpierw analizuje wiersz w pliku wsadowym, aby dowiedzieć się, co powinien zrobić, i zwykle rozszerza zmienne w tym czasie (%variablename%
). Następnie wykonuje linię.EnableDelayedExpansion
oznacza rozwinięcie zmiennych w wykrzyknikach (!variablename!
) w czasie wykonywania. Tutaj dzieje się to, że zmienna%%q
jest rozwijana w czasie analizy, a następniecmd
dusi się!
w czasie wykonywania.