Batch – Ordner und Dateien zählen

Praktisch auf (indirekter) Anfrage:
Ziel: Anzahl der Ordner und Dateien eines Ordners zählen und verarbeiten

Diese Batch zählt Dateien und Ordner des Ordners, in dem sie sich befindet:

set /A dateien=0
set /A ordner=0
for /F %%i in ('dir /B /A-d') do set /A dateien=dateien+1
for /F %%i in ('dir /B /Ad') do set /A ordner=ordner+1
echo %dateien% Dateien und %ordner% Ordner

Ziemlich einfach.
Dateien/Ordner zählen premium: Nun erweitere ich den Grundaufbau und bastel ein Batch, die per Parameter auch noch einen Ordner entgegennimmt, der verarbeitet werden soll. Der Ordner kann beim Aufruf eingegeben werden oder man zieht einfach im Explorer einen Ordner auf die Batch Datei. Sollte der übergebene Pfad nicht schon in Anführungszeichen stehen wird er in Anführungszeichen gepackt. Wird kein Ordner als Parameter angegeben wird wieder der Ordner, in dem die Batch Datei liegt, genutzt.

@echo off
setlocal
set /A dateien=0
set /A ordner=0
set path=%~1
if (%path%)==() set path=%~dp0
set first=%path:~0,1%
set last=%path:~-1%
if not (%first%)==(^") set path=^"%path%
if not (%last%)==(^") set path=%path%"
for /F %%i in ('dir %path% /B /A-d') do set /A dateien=dateien+1
for /F %%i in ('dir %path% /B /Ad') do set /A ordner=ordner+1
echo %dateien% Dateien und %ordner% Ordner
endlocal

Kurze Codebeschreibung: Pfad auf den Parameter setzen, wenn Pfad nicht gesetzt auf den aktuellen Ordner setzen. Erstes und letztes Zeichen speichern. Beide überprüfen; wenn kein Anführungszeichen dann eins setzen. Anführungszeichen werden hier mit dem ^ Zeichen escaped. Pfad an die Zählroutinen übergeben.

Eine Frage stellt sich mir aber: Ich musste jedes Anführungszeichen escapen bis auf eins: Zeile 10 ganz am Ende. Wird dort das Anführungszeichen escaped dann funktioniert das Programm nicht mehr. Kann mir jemand sagen warum?

via: Dateien/Ordner zählen, Stringkrams, Hochkomma (Anführungszeichen) in Batch escapen

13 Kommentare

  1. Hi,

    ich glaube, dass ich dir die Frage beantworten kann: Weil doppelte Anführungszeichen in der Windows Shell reservierte Zeichen sind. In Zeile 9 musst du es escapen, damit die Shell weiß, dass das Anführungszeichen zur Variable PATH gehört und kein öffnendes Anführungszeichen ist, um die Variable einzuschließen. In Zeile 10 darfst du es nicht escapen, weil die Shell sonst denkt, dass es nicht zur Variable PATH gehört, sondern sie einschließt. Dann fehlt aber das öffnende Anführungszeichen, und das Skript läuft auf Fehler.

    Deswegen hätte ich das Skript auch etwas anders geschrieben, um solche Verwirrungen zu vermeiden:

    @echo off
    setlocal
    set /A dateien=0
    set /A ordner=0
    set path=%~1
    if (%path%)==() set path=%~dp0
    if not %path:~0,1% == ^" (set path=^"%path%)
    if not %path:~-1% == ^" (set path=%path%")
    echo %path%
    for /F %%i in ('dir %path% /B /A-d') do set /A dateien=dateien+1
    for /F %%i in ('dir %path% /B /Ad') do set /A ordner=ordner+1
    echo %dateien% Dateien und %ordner% Ordner
    endlocal
    

    Die Syntax bei IF ist

    IF Bedingung (Befehl)

    .

    Aber abgesehen davon, bevorzuge ich mittlerweile doch die PowerShell, weil sie einfach logischer und stringenter ist, als die CMD.EXE:

    param($Argument1)
    $verzeichnis = "."
    if ($Argument1){$verzeichnis = $Argument1}
    if (test-path -path $verzeichnis){
        # Mit -force werden auch versteckte Dateien und Ordner gezählt:
        $Ordner = (dir $verzeichnis -force | where {$_.mode -match "d"}).count
        $Dateien = (dir $verzeichnis -force | where {$_.mode -match "a"}).count
        "$Dateien Dateien und $Ordner Ordner"
        }
    else {
        "Das Verzeichnis gibt es nicht."
        }
    

    Viele Grüße
    Christian

  2. Vielen Dank für das Feedback, klingt einleuchtend.
    In deinem Batch Code hast du eigentlich nur die Zeilen 7-10 zusammengefasst, oder? Die Klammersetzung ist in Batch ja irrelevant.

    PowerShell ist so’n Thema… es ist ja sehr mächtig aber ich finde es problematisch was alles getan werden muss damit PowerShell Scripte via Doppelklick ohne Warnungen und Adminrechte ausgeführt werden können. Da muss ja vorher bisschen was eingestellt werden.
    Und das im kompletten Unternehmen durchzuführen ist erstaunlich mühsam.

    Funktionieren .ps1 PowerShell Scripte als GPO Startscript eigentlich genauso problemfrei wie Batch Scripte? Einfach als Startscript eintragen und dann wird es ausgeführt? Werden dann die Sicherheitseinstellungen von PowerShell ignoriert weil ja SYSTEM die Startscripte ausführt?

  3. Hi,

    also irrelevant finde ich die Klammersetzung in der Batch nicht, sie lässt einem dabei nur viele Freiheiten. Fehlende oder falsch gesetzte Klammern können aber zu den dollsten Fehlern oder zu merkwürdigem Verhalten führen, die schwer zu debuggen sind. Geht mir zumindest so. 😉

    Man kann einzelne Powershell-Funktionen auch in eine Batch packen, so behelfe ich mir zumindest manchmal.

    Ich würde sagen, dass PowerShell Skripte als GPO Startskripte eigentlich genauso problemfrei wie Batch Skripte funktionieren sollten. Weiß ich aber aus der Praxis nicht, da wir noch VBSkripte haben. Auch die Sicherheitseinstellungen werden m.W. über GPOs gesteuert, z.B. lassen sich PowerShell Skripte auch als Installatiosskripte über SCCM verwenden.

    Viele Grüße
    Christian

  4. Wow, mit PowerShell ist das ja deutlich kürzer…

    Da geht aber noch was… 😉

    dir /A /S %systemroot% | grep -A 2 "Anzahl der angezeigten Dateien:"
         Anzahl der angezeigten Dateien:
               277702 Datei(en), 29.807.998.088 Bytes
               58168 Verzeichnis(se), 57.664.880.640 Bytes frei
    

    Grep for Windows

    Ein Test auf “ ist aber kein muss, da diese bei Verwendung von %~1 und %~dp0 bereits ausgefiltert wurden.
    Und in jedem Verzeichnis ein Script ablegen… na ja…

    Habe mir das Batch auf die Schnelle mal ein wenig umgestrickt – ist aber noch nicht fertig.
    Auf Wunsch gebe ich die fertige Version gerne raus…

    Was habe ich gemacht?

    1. Zuordnung für die Dateierweiterung „.size“ erstellt…

    assoc .size=DFCounter.size
    ftype DFCounter.size="%SystemRoot%DFCounter.cmd"
    

    2. MakeDFCounter.cmd – erzeugt im aktuellen Verzeichnis eine Datei (DFCounter.size) mit Null Byte Größe.

    @echo off
    rem ~ MakeDFCounter - Creates a file in the current directory (DFCounter.size) with zero byte size.
    .>%CD%DFCounter.size 2>nul
    

    3. Cmd.exe unterstützt UNC-Namen für das aktuelle Verzeichnis nicht.

    reg add "HKCUSoftwareMicrosoftCommand Processor" /v DisableUNCCheck /t REG_DWORD /d 00000001
    rem ~ To activate registry changes in HKEY_CURRENT_USER without logging off:
    RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters ,1 ,Tru
    

    PUSHD/POPD (Verzeichnis wird als Netzlaufwerk gemappt) sind keine brauchbare Alternative…

    Mit Doppelklick auf die leere Datei DFCounter.size wird nun das Batch „%SystemRoot%DFCounter.cmd“ ohne Parameter gestartet und gibt die Anzahl der Dateien/Verzeichnisse im selbigen Verzeichnis aus.

    Habe dem Batch noch ein paar Optionen hinzugefügt…

    DFCounter [/?] [-help] [-install] [-remove] [-update] [Directory] [-recursiv] [-vars var1 var2 [-quiet]]

    Überlege aber noch, ob ich das nicht besser/schneller mit AutoIt lösen sollte…

    LG
    Cronus

  5. hey cronus,

    wow, coole sachen dabei! mir gefällt die art und weise des aufrufs über die .size datei, habe ich so noch nie gesehen.
    und die methode die registry ohne relog neuzuladen kannte ich auch noch nicht 😀

    also definitiv interessante features. momentan brauche ich das nicht, habe den beitrag auch auf leseranfrage geschrieben, also nicht für mich. aber wenn das tool fertig programmiert ist kannst du mir das gerne schicken, ich würde es dem artikel anfügen. für alle zukünftigen Besucher ist es bestimmt nen blick wert.

    lg

  6. Hallo Leute….
    einen schönen Tag zusammen – habe ein Problem und hoffe hier Hilfe zu finden:
    Suche vor der Zählroutine für Dateien im jeweiligen Lw, und der zweiten ZR für Ordner im jeweiligen Lw (beide lokal), zwei Möglichkeiten, die Systemmeldungen, wenn 0 (null) intern errechnet wird, zu umgehen. Beide ZR sind in einer Batch-Datei eingebunden.
    Die %dateien% und %ordner% – eigentliche Anzahl der Dateien / Ordner – werden mit anderen Angaben ein wenig grafisch in einem DOS-Fensterchen angezeigt. Nur die System-/Fehlermeldungen sind bei 0 (Dateien/Ordner) immer oben links zu sehen. Sch… – sorry – hässlich!!!
    So kam ich als „Laie“ auf die Idee, mit jeweils einer(m) ?(Routine, Schleife, Befehl, ect.)? die Zählschleifen zu umgehen; braucht man ja auch nicht, es steht dann eben „nichts“ Dateien/Ordner in der Auflistung; auch ohne jeweilige Zählschleifen für Dateien und Ordnern, die null Dateien und null Ordner ermitteln.
    Ich benötige den Wert 0 für KEINE Dateien im Lw und den jeweiligen Ordnern/Unterordnern, und den Wert 0 für KEINE Ordner im Root, um mit goto die 2 Zählschleifen zu umgehen. Wird kein Wert 0 durch die jeweiligen ZS ermittel, dann läuft ja alles wie geschmiert und keine System-/Fehlermeldungen trüben den Alltag…. supiiieee….
    Für einen „Spezialisten“ kein Problem, nehme ich mal an – vielleicht aber doch nicht, denn es gibt nirgends einen brauchbaren und ausführbaren (Programm-, Routine-, Schleifen-, ect-Text)?
    So ist das nun mal mit den 10-Mann – Firmen und „harten“ Chefs….
    Hoffentlich kennt sich hier jemand aus mit der Materie und kann mir helfen – sonst muß ich ab 29. im Kellerbüro arbeiten.
    Einen herzlichen Gruß und vielen Dank im Vorraus, Guido

  7. @Hardy – ab in den Keller… lol

    Guck mal hier…

    : M:TESTDIR
    : +---Dir1
    : ¦   ¦   datei1.txt
    : ¦   ¦
    : ¦   +---SubDir1
    : ¦           datei1.txt
    : ¦
    : +---Dir2
    : ¦   ¦   datei2.txt
    : ¦   ¦
    : ¦   +---SubDir2
    : ¦           datei2.txt
    : ¦
    : +---Dir3
    :     ¦   datei3.txt
    :     ¦
    :     +---SubDir3
    :             datei3.txt
    :
    : Wird keine Datei oder kein Verzeichnis gefunden,
    : enthaelt die jeweilige Variable den Wert 0 (Null).
    : Fehlermeldungen des Dir-Befehls werden unterdrueckt.
     
    :
    : GetFileCount.cmd M:Testdir
    :
     
    @echo off & cls
     
    set fcount=0
    set dcount=0
     
    set subfcount=0
    set subdcount=0
     
    set "scandir=%~1"
    if not exist "%scandir%" set scandir=m:Testdir
    @echo scandir = "%scandir%"
    @echo.
    call :getcount "%scandir%"
    @echo ohne Unterverzeichnisse...
    @echo Anzahl Dateien             : %fcount%
    @echo Anzahl Verzeichnisse       : %dcount%
    @echo.
    call :getsubcount "%scandir%"
    @echo mit Unterverzeichnisse...
    @echo Anzahl aller Dateien       : %subfcount%
    @echo Anzahl aller Verzeichnisse : %subdcount%
    goto :eof
     
    :getcount
    for /F %%i in ('dir "%scandir%" /B /A-d 2^>nul') do call :addfcount %%i
    for /F %%i in ('dir "%scandir%" /B /Ad  2^>nul') do call :adddcount %%i
    goto :eof
    :getsubcount
    for /F %%i in ('dir "%scandir%" /B /A-d /S 2^>nul') do call :addsubfcount %%i
    for /F %%i in ('dir "%scandir%" /B /Ad  /S 2^>nul') do call :addsubdcount %%i
    goto :eof
     
    :addfcount
    set /A fcount+=1 & goto :eof
    :adddcount
    set /A dcount+=1 & goto :eof
    :addsubfcount
    set /A subfcount+=1 & goto :eof
    :addsubdcount
    set /A subdcount+=1 & goto :eof
    
  8. Ah, gut… das sieht in der Tat besser aus!

    Wenn möglich,
    dann korrigiere doch bitte folgende Stellen im obigen Script:

    01 : M:TESTDIR
    ->

    M:TESTDIR

    25 : GetFileCount.cmd M:Testdir
    ->

    GetFileCount.cmd M:Testdir
  9. Hallo zusammen…..
    der Kellerjob ist abgewendet. Musste zwar noch einiges anpassen, aaaabbeerrr – es hat funktioniert.
    Ich danke diesem Cremium? – herzlichen Dank….
    Hat mich sehr gefreut….
    ein schönes WE, Guido (echter Name)

Schreibe einen Kommentar