Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Verzeichnistiefe vorgeben

Frage Entwicklung Batch & Shell

Mitglied: Fahrrad

Fahrrad (Level 1) - Jetzt verbinden

05.08.2010 um 16:18 Uhr, 5496 Aufrufe, 14 Kommentare

Hallo zusammen,

ich habe da ein kleines Problem bzw. eine kleine Herausforderung

ich möchte unter Windows 2003 in einer Batch die maximale Verzeichnistiefe vorgeben können, welche dann per Dir ausgegen wird,

zB mit Tiefe=3 und

C:\test1\test2\test3\test4\test5 nur noch C:\test1\test2\test3 ausgebenb wird oder

Tiefe=5

P:\ich\du\er\sie\es\wir\ihr\sie nur noch P:\ich\du\er\sie\es\

die Namen der einzelnen Verzeichnisse sind völlig willkürlich.

Letztenendes möchte ich ein Dir über ein Netzlaufwerk machen und eben nur bis zu einer vorgebbaren Tiefe rekursiv die Verzeichnisstruktur ermitteln.

Vielen Dank für Eure Bemühungen

Gruß
Fahrrad
Mitglied: 60730
05.08.2010 um 16:38 Uhr
Moin

schau dir mal

  • for /?
an
dann schaust du auf deine "Tiefe" und merkst - das Zeichen \ gibts nur dann, wenn du einen Sprung tiefer gehst.
Ergo ist deine Grenze Token das Zeichen \
  • Set /p
damit kannst du parameter füllen und die verwerten.

Gruß
Bitte warten ..
Mitglied: Friemler
05.08.2010 um 21:21 Uhr
Hallo Fahrrad,

hier mein Vorschlag zur Lösung des Problems:

@TimoBeil: So einfach, wie Du es in Deinem Posting darstellst, ist die Sache nicht. Der Knackpunkt ist, das in der FOR-Schleife eine unbekannte Anzahl von Laufvariablen entsteht, je nach Tiefe des gerade verarbeiteten Pfades. Der Code müsste also jedes mal angepasst werden.

01.
@echo off 
02.
 
03.
setlocal 
04.
 
05.
set "rootdir=%~1" 
06.
if "%rootdir:~-1%" equ "\" set "rootdir=%rootdir:~0,-1%" 
07.
 
08.
call :CountChr "%rootdir%" \ 
09.
set /a nChr+=%~2 
10.
 
11.
call :RDir "%rootdir%" %nChr% 
12.
 
13.
endlocal 
14.
exit /b 
15.
 
16.
 
17.
 
18.
:RDir 
19.
setlocal enabledelayedexpansion 
20.
 
21.
set "actdir=%~1" 
22.
 
23.
if "%actdir:~-1%" equ ":" ( 
24.
  set "actdir2=%actdir%\" 
25.
) else ( 
26.
  set "actdir2=%actdir%" 
27.
28.
 
29.
dir "%actdir2%" /-p /o:gne /a:-s 
30.
echo. 
31.
echo. 
32.
 
33.
for /f "delims=" %%d in ('dir "%actdir2%" /b /o:ne /a:-sd 2^>NUL') do ( 
34.
  set "newdir=%actdir%\%%d" 
35.
  call :CountChr "!newdir!" \ 
36.
  if !nChr! lss %~2 call :RDir "!newdir!" %~2 
37.
38.
 
39.
endlocal 
40.
exit /b 
41.
 
42.
 
43.
 
44.
:CountChr 
45.
setlocal 
46.
 
47.
set "str=%~1" 
48.
set nChr=0 
49.
 
50.
:CountChrLoop 
51.
call set "newstr=%%str:%~2=%%" 
52.
 
53.
if "%newstr%" neq "%str%" ( 
54.
  set /a nChr+=1 
55.
 
56.
  if "%str:~-1%" neq "%~2" ( 
57.
    call set "str=%%str:*%~2=%%" 
58.
    goto :CountChrLoop 
59.
60.
61.
 
62.
endlocal & set "nChr=%nChr%" 
63.
exit /b

Aufruf

Wenn Du den Code als RDir.bat abspeicherst, wird das Skript so aufgerufen:

rdir <Verzeichnis> <Tiefe>

Verzeichnis ist das Basisverzeichnis, von dem ausgegangen wird. Enthält der Pfad Leerzeichen, muss Verzeichnis in Anführungszeichen eingeschlossen werden.

Tiefe ist deine Verzeichnistiefe, wobei ein Wert von 1 nur das Basisverzeichnis listet


Einschränkungen

Für das Basisverzeichnis muss immer ein vollständiger Pfad mit Laufwerksbuchstaben angegeben werden,
z.B. E:\Ordner1\Ordner2.

Die Verzeichnisbäume, die mit dem Skript verarbeitet werden, dürfen kein Verzeichnis enthalten, in dessen Name eines der Zeichen ^&! vorkommt, sonst kommt es zu Fehlfunktionen. Vielleicht hat noch jemand eine Idee dazu.

Verzeichnisse mit gesetztem System-Attribut werden nicht verarbeitet, das führt meist sowieso nur zu Fehlermeldungen weil die Zugriffsrechte fehlen.


Erklärung

In Zeile 6 wird geprüft, ob das letzte Zeichen von Verzeichnis ein Backslash ist und dieser ggf. entfernt.

Zeile 8 ruft eine Funktion auf, die zählt, wie oft im ersten Parameter das Zeichen im zweiten Parameter (hier also \) vorkommt. Das Ergebnis wird um die übergebene Verzeichnistiefe erhöht. Die Tilde (~) bei %~2 sorgt dafür, daß, falls Tiefe in Anführungszeichen eingeschlossen wurde, diese entfernt werden. Somit kann man nicht nur Wurzelverzeichnisse als Basisverzeichnis übergeben, sondern auch ein Unterverzeichnis auf einer beliebigen Ebene.

In Zeile 11 wird das Unterprogramm RDir (die eigentliche Programmlogik) aufgerufen. Parameter sind (das bereinigte) Verzeichnis und Tiefe.

In Zeile 14 wird das Skript nach Rückkehr aus dem Unterprogramm beendet.


Unterprogramm RDir
In Zeile 19 wird die verzögerte Variablenerweiterung eingeschaltet (wird in der FOR-Schleife gebraucht, deshalb steht dort !newdir! statt %newdir%).

In Zeile 23 wird geprüft, ob das letzte Zeichen von actdir ein Doppelpunkt ist. Durch Zeile 6 wurde ja ein Backslash als letztes Zeichen des Basisverzeichnisses entfernt. actdir würde also das Wurzelverzeichnis eines Laufwerks darstellen. Wenn dem so ist, wird die Hilfsvariable actdir2 in Zeile 24 mit dem Inhalt von actdir plus einem Backslash belegt. Wenn nicht, wird actdir2 in Zeile 26 nur mit dem Inhalt von actdir belegt. Dieses Vorgehen vermeidet, das bei den folgenden DIR-Befehlen ein Ausdruck wie z.B. DIR E: entsteht, der das aktuell gesetzte Verzeichnis von Laufwerk E: listen würde. Andererseits darf in Zeile 34 actdir auf keinen Fall als letztes Zeichen einen Backslash enthalten, da das einen Fehler verursachen würde.

In Zeile 29 wird das übergebene Verzeichnis (für den Benutzer sichtbar) gelistet. /-p verhindert die seitenweise Ausgabe, /o:gne listet zuerst Verzeichnisse (g) und sortiert die Ausgabe zuerst nach dem Namen (n) und dann nach der Erweiterung (e). /a verhindert das Auflisten von Verzeichnissen mit gesetztem System-Attribut.

Durch die zwei folgenden echo. wird ein Zeilenvorschub erzeugt.

Im Kopf der FOR-Schleife in Zeile 33 wird das Verzeichnis nochmal gelistet (nur zur weiteren Verarbeitung in der FOR-Schleife). Durch die Option /b werden jedoch nur Namen ohne Pfad, ohne den üblichen Kopf der Ausgabe von DIR und ohne Zusammenfassung (xxx Bytes frei usw.) ausgegeben. /o:ne sorgt wieder für eine sortierte Ausgabe. Das g fehlt gegenüber dem ersten DIR-Befehl, weil durch /ad sowieso nur Verzeichnisse gelistet werden, deren System-Attribut gelöscht ist. Durch 2^>NUL wird verhindert, das bei einem leeren Verzeichnis die Fehlermeldung "Datei nicht gefunden" ausgegeben wird.

Durch "delims=" im Kopf der FOR-Schleife wird der gesamte Inhalt einer Zeile der Ausgabe des DIR-Befehls der Laufvariablen %%d zugewiesen, pro Schleifendurchlauf eine Zeile. Ohne "delims=" würde nur der Inhalt einer Zeile bis zum ersten Leerzeichen zugewiesen.

In Zeile 34 wird somit der Name eines Verzeichnisses an das aktuelle Verzeichnis angehängt.

Durch den Aufruf von CountChr in Zeile 29 wird wieder gezählt, wie viele Backslashes der daraus resultierende Pfad enthält.

In Zeile 36 wird geprüft, ob damit die maximale Pfadtiefe erreicht ist, wenn nicht, ruft sich RDir mit dem neuen Pfad und der maximalen Pfadtiefe selbst auf. Der Ablauf beginnt somit eine Verzeichnisebene tiefer von neuem.


Funktion CountChr
In Zeile 51 werden alle Zeichen des 1. Parameters %1 (str), die gleich dem zweiten Parameter %2 sind, gelöscht und das Ergebnis newstr zugewiesen. str behält aber seinen bisherigen Inhalt. Die Bedeutung der Tilde (~) bei %~2 wurde weiter oben schon erklärt.

In Zeile 53 wird geprüft, ob newstr ungleich str ist. Wenn str das Zeichen aus %2 enthält, ist das der Fall. Deshalb wird der Zähler nChr in Zeile 54 um eins hochgezählt.

In Zeile 56 wird geprüft, ob das letzte Zeichen von str dem Zeichen entspricht, dessen Auftreten gezählt werden soll, wenn ja wird das Unterprogramm beendet. Diese Abfrage ist nur nötig, weil der Befehl in Zeile 57 in diesem Spezialfall nicht funktioniert.

In Zeile 57 wird nämlich in str alles vor dem ersten Auftreten des Zeichens, dessen Vorkommen gezählt werden soll, inkl. dem Zeichen selbst, gelöscht und das Ergebnis wieder str zugewiesen. Dann erfolgt ein Sprung zum Anfang der Schleife, im Endeffekt also nach Zeile 51.

Durch Zeile 57 wird also schrittweise jedes Auftreten des gesuchten Zeichens eliminiert und ein neuer Durchlauf gestartet, also der Zähler nChr um 1 inkrementiert. Wenn das gesuchte Zeichen in str garnicht mehr vorkommt, sorgt Zeile 53 für einen Abbruch der Schleife. Wenn es nur noch einmal am Ende von str vorkommt, sorgt Zeile 56 für den Abbruch (vorher wurde es aber schon gezählt).

Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
09.08.2010 um 08:41 Uhr
Moin Friemler,

vielen vielen Dank für Deine ausführliche Beschreibung & Hilfe!!!!!

Ich habe es ausprobiert und habe folgende Probleme

Ich brauche nur die Verzeichnisnamen, also habe ich im Skript DIR nur mit /AD /S /B aufgerufen

Er zeigt mit trotzdem ALLE Verzeichnisse an ;o(, nicjht nur bis zur Ebene, welche ich vorgegeben habe

Anbei das geänderte Skript

@ECHO OFF

setlocal

set "rootdir=%~1"
if "%rootdir:~-1%" equ "\" set "rootdir=%rootdir:~0,-1%"

call :CountChr "%rootdir%" \
set /a nChr+=%~2

call :RDir "%rootdir%" %nChr%

endlocal
exit /b



:RDir
setlocal enabledelayedexpansion

set "actdir=%~1"

if "%actdir:~-1%" equ ":" (
set "actdir2=%actdir%\"
) else (
set "actdir2=%actdir%"
)

dir "%actdir2%" /AD /S /B
echo.
echo.

for /f "delims=" %%d in ('dir "%actdir2%" /AD /S /B 2^>NUL') do (
set "newdir=%actdir%\%%d"
call :CountChr "!newdir!" \
if !nChr! lss %~2 call :RDir "!newdir!" %~2
)

endlocal
exit /b



:CountChr
setlocal

set "str=%~1"
set nChr=0

:CountChrLoop
call set "newstr=%%str:%~2=%%"

if "%newstr%" neq "%str%" (
set /a nChr+=1

if "%str:~-1%" neq "%~2" (
call set "str=%%str:*%~2=%%"
goto :CountChrLoop
)
)

endlocal & set "nChr=%nChr%"
exit /b

Gruß
Fahrrad
Bitte warten ..
Mitglied: Friemler
09.08.2010 um 10:04 Uhr
Hallo Fahrrad,

der Parameter /S beim DIR-Befehl bewirkt, das alle Verzeichnisse angezeigt werden. Die Verzeichnisstruktur wird dann von DIR rekursiv durchlaufen. Zeile 29 muss für Deinen Fall lauten:
dir "%actdir2%" /-p /b /o:ne /a:-sd
Entscheidend ist das gegenüber dem Original zusätzliche d bei /ad, dadurch werden nur Verzeichnisse gelistet.

Zeile 33 muss so bleiben, wie in meinem Original-Skript, also
for /f "delims=" %%d in ('dir "%actdir2%" /b /o:ne /a:-sd 2^>NUL') do (
In Deinen geänderten Befehlszeilen hast Du geschrieben /AD, das -s fehlt also. Dadurch werden auch Verzeichnisse mit gesetztem System-Attribut verarbeitet, je nach dem wie die Umgebungsvariable DIRCMD eingestellt ist. Das würde wahrscheinlich zu Problemen führen.

Das alles hätte Dir aber auch die Hilfe zum DIR-Befehl verraten .

Programmcode schließt man beim Posten in code-Tags ein, dann erscheinen die Zeilennummern und Einrückungen bleiben erhalten.

Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
09.08.2010 um 10:48 Uhr
Hallo Friemler,

soweit funktioniert es gut. Ich habe mich aber wohl nicht so ganz klar ausgedrückt ;o((

Als Beispiel mal ein DIR /S /AD /B:

E:\Ich\Baum\Blinker
E:\Ich\Baum\Blinker\Access
E:\Ich\Baum\Blinker\Desktop
E:\Ich\Baum\Blinker\EnterpriseGuide
E:\Ich\Baum\Blinker\Eis
E:\Ich\Baum\Blinker\Eis\Dom
E:\Ich\Baum\Blinker\Eis\Dom\THW
E:\Ich\Baum\Blinker\Eis\Dom\THW\10.00
E:\Ich\Baum\Blinker\Eis\Dom\THW\10.00\Accessories

Ich brauche in meinem Ergebnis zur weiteren Verarbeitung alle Verzeichnisse bis Tiefe 5

Im beispiel also alles bis E:\Ich\Baum\Blinker\Eis\Dom, alles was danach kommt soll wegfallen, so daß nur

E:\Ich\Baum\Blinker
E:\Ich\Baum\Blinker\Access
E:\Ich\Baum\Blinker\Desktop
E:\Ich\Baum\Blinker\Enterprise
E:\Ich\Baum\Blinker\Eis
E:\Ich\Baum\Blinker\Eis\Dom
E:\Ich\Baum\Blinker\Eis\Dom
E:\Ich\Baum\Blinker\Eis\Dom
E:\Ich\Baum\Blinker\Eis\Dom

übrig bleibt.


Tja, wer lesen kann ist klar im Vorteil, ich war nur auf etwas verbeohrt.....

Gruß & Danke
Fahrrad
Bitte warten ..
Mitglied: Friemler
09.08.2010 um 10:56 Uhr
Hallo Fahrrad,

Zitat von Fahrrad:
Tja, wer lesen kann ist klar im Vorteil

dann beherzige das mal. Um Dein gewünschtes Ergebnis zu erzielen lautet der Aufruf meines Skripts:
rdir E:\Ich 4
oder
rdir E:\ 5
wenn auf E: nur das Verzeichnis Ich existiert.

[Edit]
OK, um die kompletten Pfade ausgegeben zu bekommen, muss noch was geändert werden. Melde mich nochmal.

Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
09.08.2010 um 11:06 Uhr
Moin Friemler,

dann erhalte ich zwar schon die "relativen" Verzeichnisse,

Blinker
Access
Desktop
Enterprise
Eis
Dom

aber nicht die absoluten

E:\Ich\Baum\Blinker
E:\Ich\Baum\Blinker\Access
E:\Ich\Baum\Blinker\Desktop
E:\Ich\Baum\Blinker\Enterprise
E:\Ich\Baum\Blinker\Eis
E:\Ich\Baum\Blinker\Eis\Dom

wobei ein DOm natürlich reichen würde

Sorry für mein dickes brett vorm Kopf

Gruß & Danke
Fahrrad
Bitte warten ..
Mitglied: Friemler
09.08.2010 um 11:17 Uhr
Hallo Fahrrad,

sorry, jetzt hatte ICH das Brett vorm Kopf.

Ersetze die Zeilen
01.
dir "%actdir2%" /-p /b /o:ne /a:-sd 
02.
echo. 
03.
echo.
durch
01.
for /f "delims=" %%d in ('dir "%actdir2%" /b /o:ne /a:-sd 2^>NUL') do ( 
02.
  echo %actdir%\%%d 
03.
)
Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
09.08.2010 um 11:24 Uhr
Vielen vielen Dank

Es fubnktioniert wie ich es möchte
Bitte warten ..
Mitglied: Friemler
18.08.2010 um 03:43 Uhr
@All,

ich poste hier noch eine verbesserte Version des Skripts. Es entspricht in der Funktionsweise dem Wunsch von Fahrrad, hat aber keine Einschränkungen bzgl. der Zeichen !^& und kann auch relative Pfade als Basisverzeichnis verarbeiten (also . oder .. oder P: oder Verz1\Verz2 usw.).

Die Einschränkung bzgl. der Zeichen !^& wird erstens durch die Zeilen 6, 24, 46 und 47 und zweitens durch Auslagerung der Verzeichnisausgabe und der Zeilen 35 und 36 aus dem ursprünglichen Skript in das Unterprogramm ProcessDir beseitigt (kein enabledelayedexpansion nötig, dadurch auch keine Schwierigkeiten mit dem !).

Für die Verzeichnisausgabe in Zeile 49 müssen evtl. vorhandene & Zeichen escaped werden, deshalb Zeile 46.

In einem Batch-Skript ersetzt der Skript-Interpreter beim Aufruf eines anderen Batch-Skripts/eines Unterprogramms in den Parametern jedes ^ durch ^^. Deshalb die Zeilen 6, 24 und 47. Beim Aufruf von der Kommandozeile findet diese Ersetzung jedoch nicht statt. Dadurch ergibt sich ein Unterschied beim Aufruf von der Eingabeaufforderung und beim Aufruf aus einem Batch-Skript. Wenn man z.B. ein Verzeichnis "E:\Test ^^ Test" hat, das man meinem Skript als Basisverzeichnis übergeben will, lautet der Aufruf von der Eingabeaufforderung (X=gewünschte Tiefe)
DepthDir "E:\Test ^^^^ Test" X
und aus einem Batch-Skript
call DepthDir.bat "E:\Test ^^ Test" X
Relative Pfade können durch %~f1 bei set "rootdir=%~f1" in Zeile 5 verarbeitet werden. Dadurch wird der Parameter %1 erstens von umgebenden Anführungszeichen befreit (die Tilde ~) und zweitens zu einem vollständigen Verzeichnispfad erweitert (das f). Aus . wird also das aktuell gesetzte Verzeichnis, aus .. das übergeordnete Verzeichnis des aktuellen Verzeichnisses, aus P: das aktuelle Verzeichnis von Laufwerk P:.

Die Funktion CountChr habe ich auch geändert, da sie noch einen Fehler enthielt, der zwar bei dem ursprünglichen Skript nie zum Tragen kam, aber jetzt ist sie allgemein verwendbar und gibt ihr Ergebnis in ERRORLEVEL zurück.

Hier das Skript:
01.
@echo off 
02.
 
03.
setlocal 
04.
 
05.
set "rootdir=%~f1" 
06.
set "rootdir=%rootdir:^^=^%" 
07.
 
08.
if "%rootdir:~-1%" equ "\" set "rootdir=%rootdir:~0,-1%" 
09.
 
10.
call :CountChr "%rootdir%" \ 
11.
set /a depth=%errorlevel%+%~2 
12.
 
13.
call :RDir "%rootdir%" %depth% 
14.
 
15.
endlocal 
16.
exit /b 
17.
 
18.
 
19.
 
20.
:RDir 
21.
setlocal 
22.
 
23.
set "actdir=%~1" 
24.
set "actdir=%actdir:^^=^%" 
25.
 
26.
if "%actdir:~-1%" equ ":" ( 
27.
  set "actdir2=%actdir%\" 
28.
) else ( 
29.
  set "actdir2=%actdir%" 
30.
31.
 
32.
for /f "delims=" %%d in ('dir "%actdir2%" /b /o:ne /a:-sd 2^>NUL') do ( 
33.
  call :ProcessDir "%actdir%\%%d" %2 
34.
35.
 
36.
endlocal 
37.
exit /b 
38.
 
39.
 
40.
 
41.
:ProcessDir 
42.
setlocal 
43.
 
44.
set "newdir=%~1" 
45.
 
46.
set "newdir2=%newdir:&=^&%" 
47.
set "newdir=%newdir:^^=^%" 
48.
 
49.
echo %newdir2% 
50.
 
51.
call :CountChr "%newdir%" \ 
52.
if %errorlevel% lss %2 call :RDir "%newdir%" %2 
53.
 
54.
endlocal 
55.
exit /b 
56.
 
57.
 
58.
 
59.
:CountChr 
60.
setlocal 
61.
 
62.
set "str=%~1" 
63.
 
64.
if "%str:~-1%" neq "%~2" ( 
65.
  set nChr=0 
66.
) else ( 
67.
  set nChr=1 
68.
  set "str=%str:~0,-1%" 
69.
70.
 
71.
:CountChrLoop 
72.
call set "newstr=%%str:%~2=%%" 
73.
 
74.
if "%newstr%" neq "%str%" ( 
75.
  set /a nChr+=1 
76.
 
77.
  call set "str=%%str:*%~2=%%" 
78.
  goto :CountChrLoop 
79.
80.
 
81.
exit /b %nChr%
Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
18.08.2010 um 15:08 Uhr
Hallo Friemler,

die Einschränkungen sind mir soweit auch schon bei Pfaden mit den Sonderzeichen aufgefallen und jetzt läuft es fast so wie ich es möchte.....

Dein Skript möchte ich als Unterroutine in ein bestehendes Skript einbinden, d.h. Param1 und Param2 werden vorher schon als Directory (ohne abschließenden \) und Depth gesetzt.

Danke & Gruß
Fahrrad
Bitte warten ..
Mitglied: Friemler
18.08.2010 um 17:12 Uhr
Hallo Fahrrad,

Zitat von Fahrrad:
... jetzt läuft es fast so wie ich es möchte.....

Wo hapert es denn noch?

Wenn Du ein Wurzelverzeichnis (z.B. P:\) als Basisverzeichnis angibst, ist der abschließende Backslash richtig und nötig. Also nicht pauschal einen abschließenden Backslash bei Parameter 1 entfernen.

Gruß
Friemler
Bitte warten ..
Mitglied: Fahrrad
19.08.2010 um 07:48 Uhr
Moin Friemler,

tja, da ist wohl wieder oder immer noch ein dickes brett....

ich möchte im Skript am Anfang (also sozusagen "hardcodiert")

set directory=P:\test und

Depth=4 setzen.

"Deine" Unterroutine soll dann bei Aufruf mit diesen beiden Variablen arbeiten.

Da hapert es noch ;o(

Danke & gruß
Fahrrad
Bitte warten ..
Mitglied: Friemler
19.08.2010 um 13:06 Uhr
Hallo Fahrrad,

ich weiß jetzt zwar immer noch nicht, wo das Problem liegt , aber mal ein paar Tipps ins Blaue.

  • Ersetze das @echo off in der ersten Zeile durch eine Sprungmarke, z.B. :DepthDir (Doppelpunkt nicht vergessen). Nimm auf jeden Fall einen Namen, der von den Sprungmarken, die im Skript schon verwendet werden, verschieden ist.

  • Die Sprungmarke muss am Zeilenanfang stehen, der Doppelpunkt ist also das erste Zeichen der Zeile.

  • Wenn Du am Anfang Deines Skripts
set "directory=P:\Test" 
set "depth=4"
schreibst, lautet der Aufruf meines Unterprogramms
call :DepthDir "%directory%" %depth%
  • Wenn Du die Ausgabe meines Skripts weiterverarbeiten willst, um irgendwelche Operationen in den gelisteten Verzeichnissen auszuführen, musst Du das Skript z.B. als DepthDir.bat speichern (dann mit @echo off in der ersten Zeile, keine Sprungmarke). Der Aufruf wäre dann folgendermaßen, wenn DepthDir.bat im gleichen Verzeichnis wie Dein Hauptskript gespeichert ist:
01.
@echo off 
02.
 
03.
setlocal 
04.
 
05.
set "directory=P:\Test" 
06.
set "depth=2" 
07.
 
08.
for /f "delims=" %%d in ('call "DepthDir.bat" "%directory%" %depth%') do ( 
09.
  call :ListDir "%%d" 
10.
11.
 
12.
endlocal 
13.
exit /b 
14.
 
15.
 
16.
:ListDir 
17.
setlocal 
18.
 
19.
set "outdirname=%~1" 
20.
set "outdirname=%outdirname:&=^&%" 
21.
 
22.
set "dirname=%~1" 
23.
set "dirname=%dirname:^^=^%" 
24.
 
25.
echo Dateien im Verzeichnis %outdirname% & echo. 
26.
dir /b /a:-d "%dirname%" 2>NUL || echo Das Verzeichnis ist leer oder enthält nur Unterverzeichnisse. 
27.
echo. & echo. & echo. 
28.
endlocal 
29.
exit /b
Das würde die Namen der Dateien in den Verzeichnissen auflisten. Bei leeren Verzeichnissen oder Verzeichnissen, die nur Unterverzeichnisse enthalten, wird die Meldung "Das Verzeichnis ist leer oder enthält nur Unterverzeichnisse." ausgegeben.

Die Verwendung des Unterprogramms ListDir und darin der Variablen outdirname und dirname hat mit der Problematik der Zeichen ^&! zu tun. Da beim DIR-Befehl in Zeile 26 %dirname% in Anführungszeichen übergeben wird, kann es ruhig das Zeichen & enthalten. Für den ECHO-Befehl in Zeile 25 gilt das nicht, deshalb wird dort %outdirname% verwendet, in dem & escaped ist. Umgekehrt muss bei einem Pfad wie "P:\Test\Test ^ Test" (der an ListDir in der Form P:\Test\Test ^^ Test übergeben wird, siehe Erklärung bei geändertem neuem Skript) das doppelte ^ durch ein einfaches ^ ersetzt werden, damit DIR das Verzeichnis auch findet; ECHO benötigt aber das doppelte ^ im String (^ wird escaped), damit es in der Ausgabe nur noch einfach erscheint (wenn Du dich jetzt am Kopf kratzt, experimentiere mal ein wenig mit dem Code ).

Das obige Beispiel zeigt auch, was zu machen ist, wenn Du an den Verzeichnispfaden in der FOR-Schleife etwas manipulieren musst: Die Manipulation in ein Unterprogramm auslagern. Ansonsten musst Du mit SETLOCAL ENABLEDELAYEDEXPANSION arbeiten, in der FOR-Schleife die Laufvariable an eine Hilfsvariable zuweisen und die bei Stringmanipulationen mit ! einschließen. Und schon gibt es wieder Probleme mit Pfaden, die ein ! enthalten.


Vielleicht war ja ein Tipp dabei, der Dir hilft.



[EDIT]

Ich habe mein neues Skript nochmal geändert, da es immer noch zu Fehlern mit dem Zeichen ^ in Pfadnamen kam.


Gruß
Friemler
Bitte warten ..
Neuester Wissensbeitrag
Ähnliche Inhalte
Exchange Server
Anmeldezeiten vorgeben für Domänenbenutzer jedoch nicht für Exchange (7)

Frage von bandiandi zum Thema Exchange Server ...

Windows 10
WIn 10 Anmelde-Bild über Domain vorgeben

Frage von Rocki4455 zum Thema Windows 10 ...

Heiß diskutierte Inhalte
Windows Userverwaltung
Ausgeschiedene Mitarbeiter im Unternehmen - was tun mit den AD Konten? (32)

Frage von patz223 zum Thema Windows Userverwaltung ...

LAN, WAN, Wireless
FritzBox, zwei Server, verschiedene Netze (21)

Frage von DavidGl zum Thema LAN, WAN, Wireless ...

Viren und Trojaner
Aufgepasst: Neue Ransomware Goldeneye verbreitet sich rasant (20)

Link von Penny.Cilin zum Thema Viren und Trojaner ...

Windows Netzwerk
Windows 10 RDP geht nicht (18)

Frage von Fiasko zum Thema Windows Netzwerk ...