chocoloco
Goto Top

Datei in ganz bestimmten Ordner suchen und ausführen

Hallo erstmal an alle,

da ich mich seit kurzem mit Batchprogrammierung beschäftige und bei euch schon sehr viele hervorragende Hinweise zu anderen Problemen dieser Art gefunden habe würde ich jetzt gerne meine eigene Frage stellen. Ich habe ca 100 Ordner mit einer ganz bestimmten, immer gleichen Unterordnerstruktur. Jetzt muss ich mehrere Programme nacheinander ausführen. Ein Beispiel, dass ich gelöst habe:
@ECHO OFF

for /r %BASE_DIR% %%i in (*.frd *.dat *.sta 2014-07-04_turbine_blade_Mesh.inp) do (
del %%i
echo %%i
)
Wie ihr sicherlich gleich erkennt, wird im %BASE_DIR% nach (*.frd *.dat *.sta 2014-07-04_turbine_blade_Mesh.inp) gesucht und diese anschließend gelöscht.


Bei einem zweiten Problem schaffe ich es mit dem gleichen Vorgehen bestimmte Dateien mit einem Programm auszuführen.
@ECHO OFF

for /r %BASE_DIR% %%i in (2014-07-04_turbine_blade) do (
cd RUN_*\Output
ccx %%~fi
echo %%i
echo %%~fi
)
Bei beiden Beispielen war es allerdings egal, ob der Pfad richtig war, denn bei einem falschen Pfad wurde dieser einfach nicht ausgeführt. Ganz nebenbei weiß ich nicht, warum ich dieses cd RUN_*\Output brauche, aber ohne dem gehts nicht.

Nun habe ich aber das Problem, dass ich bei einem Programm eine Fehlermeldung bekomme, wenn der Pfad nicht genau stimmt, d.h. ich darf nur in Ordnern suchen, die die Datei auch enthalten! Hier im Forum bin ich auch auf ähnliche Dinge gestoßen, aber leider reicht mein Batchwissen nicht aus, um sie auf meinen Fall umzusetzen.
Folgende Ordnerstruktur
%BASE_DIR%
- RUN_1
-- Input
-- Output
-- Project
- RUN_2
-- Input
-- Output
-- Project
usw.

Die gesuchte Datei befindet sich immer in -- Project. Leider funktioniert mein Ansatz nicht (war nicht mein einziger):
for /r %BASE_DIR%\RUN_*\Project %%i in (Project.sls) do (
cd RUN_1\Project
START CMD /wait /c %SIMLAB_DIR%\SimLab.bat -auto %%~fi -nographics -nowait
)

Bin um jede Hilfe sehr dankbar.

Schöne Grüße
ChocoLoco

Content-Key: 243434

Url: https://administrator.de/contentid/243434

Printed on: April 18, 2024 at 12:04 o'clock

Member: rubberman
rubberman Jul 11, 2014, updated at Jul 12, 2014 at 14:23:06 (UTC)
Goto Top
Hallo ChocoLoco, willkommen im Forum.

Das Problem ist einfach erklärt: Es wird nur dann nach einer Datei gesucht, wenn in der Klammer ein Wildcard Zeichen (* oder ?) zu finden ist. Anderenfalls wird der Dateiname einfach an jedes gefundene Verzeichnis angehängt. Wildcards im Pfad funktionieren nicht, aber das hast du bereits herausgefunden.

Es mag komisch aussehen, aber wenn du ein Wildcard an deinen Dateinamen anhängst, sollte es funktionieren.
Ungetestet:
for /r "%BASE_DIR%" %%i in (Project.sls*) do (  
  start "" /d "%%~dpi" /wait CMD /c "%SIMLAB_DIR%\SimLab.bat" -auto "%%~fi" -nographics -nowait  
)
Option /d ändert das Arbeitsverzeichnis des aufgerufenen Programms.

Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 11, 2014 at 23:58:49 (UTC)
Goto Top
Hallo rubberman,

danke für deinen Hinweis. Leider funktioniert es so nicht. Wenn ich die Befehlszeile in die ursprüngliche Form bringe
START CMD /wait /c %SIMLAB_DIR%\SimLab.bat -auto %%~fi -nographics -nowait
dann haut es wieder hin, aber mit Fehlermeldungen. Mir ist auch nicht klar, was diese Zusätzlichen Parameter bedeuten. Vielleicht kannst du hierzu noch etwas sagen.

Bei meiner zweiten Lösung (siehe ersten Beitrag) würde ich auch gerne mit * arbeiten, aber dann wird die Endung angehängt. Das klappt mit dem Prgramm nicht, da ich den Dateinamen ohne Endung angeben muss und dieser dann automatisch von der exe hinzufügt wird, also quasi Dateiname.ENDUNG.ENDUNG (in meinem Fall wäre das 2014-07-04_turbine_blade.inp.inp).
Member: rubberman
rubberman Jul 12, 2014 updated at 14:23:12 (UTC)
Goto Top
Hallo ChocoLoco,

ganz kann ich dir noch nicht folgen.
Wenn ich die Befehlszeile in die ursprüngliche Form bringe
/wait gehört zum START Befehl und muss demnach vor CMD stehen.
Mir ist auch nicht klar, was diese Zusätzlichen Parameter bedeuten.
Welche? Zum /d habe ich etwas geschrieben.
Bei meiner zweiten Lösung (siehe ersten Beitrag) würde ich auch gerne mit * arbeiten, aber dann wird die Endung angehängt.
An der Stelle hast du mich endgültig verloren. Aber mal als Tipp: %%~dpni ergibt Laufwerk, Pfad und Dateiname von %%i (ohne Dateiendung).

Für Hilfe zu den einzelnen Befehlen, öffne ein CMD Fenster und führe
Befehl /?
aus. In deinem Fall FOR /? und START /?.

Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 12, 2014 updated at 13:51:10 (UTC)
Goto Top
Hallo rubberman,

es ist nicht ganz trivial, aber ich versuche mal, dass ganze Problem auf den Punkt zu bringen. Wie erwähnt habe ich folgende Ordnerstruktur:
%BASE_DIR%
- RUN_1
-- Input
-- Output
-- Project
- RUN_2
-- Input
-- Output
-- Project
usw.

Die genaue Anzahl der Ordner kenne ich nicht, das kann variieren, allerdings kenne ich den exakten Aufbau, der in jedem einzelnen RUN gleich ist. Des Weiteren weiß ich, wo genau die Dateien liegen, die ich mit den Programmen ansprechen will, d.h. ich müsste nicht immer die ganze Struktur durchsuchen, sondern es würde reichen sequentiell alle RUNs und die beinhalteten Dateien anzusprechen. Die pauschale Suche nach den Dateien in ALLEN Ordnern ist nur eine NOTLÖSUNG von mir, weil ich es nicht besser hinbekomme. Was ich errichen möchte:
Bsp:
RUN_1
Programm A:
1. Verwende DateiA in Ordner RUN_1\Output\DateiA und führe die Aktion aus
2. Verwende DateiA in Ordner RUN_1\Output\DateiA und führe die Aktion aus
3. usw. bis die letzte Aktion in dem RUN abgearbeitet ist.

Programm B:
1. Verwende DateiB in Ordner RUN_1\Project\DateiB und führe die Aktion aus
2. Verwende DateiA in Ordner RUN_1\Project\DateiA und führe die Aktion aus
3. usw. bis die letzte Aktion in dem RUN abgearbeitet ist.

Programm C:
usw.

RUN_2
Programm A:
1. Verwende DateiA in Ordner RUN_2\Output\DateiA und führe die Aktion aus
2. Verwende DateiA in Ordner RUN_2\Output\DateiA und führe die Aktion aus
3. usw. bis die letzte Aktion in dem RUN abgearbeitet ist.

Programm B:
1. Verwende DateiB in Ordner RUN_2\Project\DateiB und führe die Aktion aus
2. Verwende DateiA in Ordner RUN_2\Project\DateiA und führe die Aktion aus
3. usw. bis die letzte Aktion in dem RUN abgearbeitet ist.

Programm C:
usw.

Das Problem auf den Punkt gebracht: Jedes Programm soll nur auf die richtige Datei zugreifen, am liebsten ohne alle (unwichtigen) Ordner zu durchsuchen.

Schöne Grüße
ChocoLoco
Member: rubberman
Solution rubberman Jul 12, 2014 updated at 15:02:24 (UTC)
Goto Top
Hallo ChocoLoco.

Teste:
for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%%~i\Project\Project.sls" (  
    echo "%%~i\Project\Project.sls" gefunden  
    REM Hier wuerde deine START Zeile stehen ...
  ) else (
    echo "%%~i\Project\Project.sls" NICHT gefunden  
  )
)
Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 12, 2014 updated at 14:53:13 (UTC)
Goto Top
Vielen Dank, das sieht schon sehr gut aus! Leider bleibt die Fehlermeldung face-sad

Ganz soweit war ich, denke ich, gar nicht weg. Mein angepasster code lautet:
@ECHO OFF

for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%%~i\Project\Project.sls" (  
    echo "%%~i\Project\Project.sls" gefunden  
    REM Hier wuerde deine START Zeile stehen ...
    CMD /wait /c %SIMLAB_DIR%\SimLab.bat -auto "%%~i\Project\Project.sls" -nographics -nowait  
  ) else (
    echo "%%~i\Project\Project.sls" NICHT gefunden  
  )
)
Das wait habe ich nach vorne gesetzt, so wie du es mir empfohlen hast.

Update: Sorry für das schnelle Update, aber ich habe gerade herausgefunden, dass die Fehlermeldung nichts mit der Batch zu tun hat.


PS: Kannst du mir sagen, wie ich Bilder hochladen und einbinden kann?
Member: rubberman
rubberman Jul 12, 2014 updated at 14:56:42 (UTC)
Goto Top
Hehe, also nochmal, ein /wait gibt es nicht für cmd (das passiert automatisch). Rausschmeißen! Die Variable %BASE_DIR% musst du natürlich auch am Anfang des Codes definieren.
Und wie genau lautet die Fehlermeldung?

Bilder hochladen? Findest du in der Hilfe.
Member: ChocoLoco
ChocoLoco Jul 12, 2014 at 15:02:13 (UTC)
Goto Top
Um den ganzen Ablauf zu starten benutze ich eine MASTER.bat, dort sind auch die Variablen definiert:
@ECHO ON

REM Verzeichnisvariablen
set RUN_DIR_1=RUN_1
set RUN_DIR_2=RUN_2
set BASE_DIR=D:\00_Dipl_Turbine
set SIMLAB_DIR=D:\SimLab_130\

REM Vorherige Output Dateien löschen
call .\linkMASTER\01_linkMASTER_LOESCHEN_output.bat

REM SimLab
call .\linkMASTER\02_linkMASTER_SimLab.bat
Member: ChocoLoco
ChocoLoco Jul 12, 2014 at 15:38:50 (UTC)
Goto Top
Hey rubberman,

es scheint alles PERFEKT(!!!!!!) zu funktionieren. Nach mehreren Tagen intensiver Arbeit und deiner hervorragenden Hilfe!

Ganz herzlichen Dank! face-smile


Schöne Grüße
ChocoLoco

PS: Die Fehlermeldung ist von dem auszuführenden Programm erzeugt worden und hatte nichts mit der Bat-Datei zu tun. Nach einigen Neuinstallationen und Pfadanpassungen funktioniert jetzt auch das.
Member: ChocoLoco
ChocoLoco Jul 12, 2014 at 17:23:10 (UTC)
Goto Top
Hallo nochmal,

es gibt doch noch eine Kleinigkeit. Das letzte Programm in der Kette greift auf Dateien zurück, die sich in Ordnern befinden, die sich ebenfalls ändern. Ich versuche es an einem Beispiel klar zu machen. Folgendes habe ich, dank Dir, ja bereits:
for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%BASE_DIR%\new_model.prt" (  
    cd %BASE_DIR%
    generate_evaluation_grid.exe new_model.prt Expression\Expression_1\profil_veraendert.exp 0.5
    MOVE "%BASE_DIR%\elemente_base.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\elemente_mod.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\fem1.fem" "%%~i\Output"  
    MOVE "%BASE_DIR%\knoten_base.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\knoten_mod.txt" "%%~i\Output"  
  ) else (
    echo "%BASE_DIR%\new_model.prt" NICHT gefunden  
  )
)

Beachte Zeile 04.
generate_evaluation_grid.exe new_model.prt Expression\Expression_1\profil_veraendert.exp 0.5
Das Programm generate_evaluation_grid.exe greift auf die Datei new_model.prt zu und variiert Parameter, die das Programm von Expression\Expression_1\profil_veraendert.exp bezieht.
Momentan verwendet das Programm für jeden Run Expression\Expression_1, tatsächlich soll sich die Zahl der Expression aber mit dem RUN erhöhen, d.h.
Run_1 --> Expression\Expression_1\profil_veraendert.exp
Run_2 --> Expression\Expression_2\profil_veraendert.exp
Run_3 --> Expression\Expression_3\profil_veraendert.exp
usw.

Kannst Du mir einen Hinweis geben wie ich das anpassen kann?


Schöne Grüße
ChocoLoco
Member: rubberman
Solution rubberman Jul 12, 2014, updated at Jul 13, 2014 at 11:04:12 (UTC)
Goto Top
Ups, gar nicht mitbekommen, dass hier noch was kam.
Um das hinzubekommen, musst du den Run_... Verzeichnisnamen am Unterstrich splitten. Ich versuch's mal ungetestet in den Browser zu schreiben.
Für Zeile 4 folgende Zeilen:
    for /f "tokens=2 delims=_" %%j in ("%%~ni") do (  
      generate_evaluation_grid.exe new_model.prt Expression\Expression_%%j\profil_veraendert.exp 0.5
    )
Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 13, 2014 at 11:16:44 (UTC)
Goto Top
Also jetzt mal ungelogen, Du bist echt der Hit! Vielen Dank!!! face-smile
So sieht der Code aus und funktioniert wunderbar:
for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%BASE_DIR%\new_model.prt" (  
    for /f "tokens=2 delims=_" %%j in ("%%~ni") do (  
	cd %BASE_DIR%    
        generate_evaluation_grid.exe new_model.prt Expression\Expression_%%j\profil_veraendert.exp 0.5
  )
    MOVE "%BASE_DIR%\elemente_base.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\elemente_mod.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\fem1.fem" "%%~i\Output"  
    MOVE "%BASE_DIR%\knoten_base.txt" "%%~i\Output"  
    MOVE "%BASE_DIR%\knoten_mod.txt" "%%~i\Output"  
  ) else (
    echo "%BASE_DIR%\new_model.prt" NICHT gefunden  
  )
)
Durch meine Recherche dachte ich mir schon, dass ich hier mit "Delim" arbeiten muss, habe die Anwendung des Befehls aber nicht ganz verstanden. Dein Beispiel bringt gut Licht in die Sache, auch in die Anwendung und Verschachtelung des FOR Befehls.

Ohne Deine Hilfsbereitschaft zu sehr beanspruchen zu wollen hätte ich eine letzte Frage. Der ganze Ablauf funktioniert momentan einwandfrei, allerdings seriell. Bei mind. 100 Durchläufen, wobei eine Berechnung ca. 1std dauert, brauche ich etwa 1 Woche. Jetzt würde ich die Berechnung gerne parallelisieren, d.h. bei jedem Durchlauf ca. 4 Berechnungen gleichzeitig starten. Denkst Du, das ist möglich? Etwa so (wobei das nicht funktioniert):
for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%%~i\Output\2014-07-04_turbine_blade_Mesh.inp" (  
    cd "%%~i\Output"  
    ccx "%%~i\Output\SOLVER_2014-07-04_turbine_blade"  
    ccx "%%~i+1\Output\SOLVER_2014-07-04_turbine_blade"  
    ccx "%%~i+2\Output\SOLVER_2014-07-04_turbine_blade"  
    ccx "%%~i+3\Output\SOLVER_2014-07-04_turbine_blade"  
  ) else (
    echo "%%~i\Output\SOLVER_2014-07-04_turbine_blade.inp" NICHT gefunden  
  )
)

Schöne Grüße
ChocoLoco
Member: rubberman
rubberman Jul 13, 2014 at 12:33:47 (UTC)
Goto Top
Um asynchron arbeiten zu können, benötigst du wieder den START Befehl.

Da das Ganze aber, wie du schreibst, trotzdem sehr viel Zeit in Anspruch nehmen wird, ist mir noch nicht klar wie du vorhast damit zu arbeiten. Willst du die Batchdatei nur einmal starten und sie läuft dann eben bis alle Dateien verarbeitet wurden? Oder willst du jeweils nachdem 4 Berechnungen durch sind die Batchdatei neu starten? Im letzteren Fall musst du mir sagen, woran zu erkennen ist, welche Berechnungen bereits erfolgt sind, damit nicht wieder bei Run_1 gestartet wird.

Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 13, 2014 updated at 12:53:50 (UTC)
Goto Top
Ich will meine Masterbatch nur einmal starten und danach soll die ganze Berechnung bis zum letzten RUN Ordner durchlaufen.
Hier der Aufbau meiner Masterdatei:
@ECHO ON

REM Verzeichnisvariablen
set BASE_DIR=D:\00_Dipl_Turbine\00_Berechnung
set SIMLAB_DIR=D:\SimLab_130\

REM --------------------------------------------
REM Vorherige Output Dateien löschen
REM --------------------------------------------
call .\linkMASTER\01_linkMASTER_Loeschen.bat

REM --------------------------------------------
REM SimLab
REM --------------------------------------------
START call .\linkMASTER\02_linkMASTER_SimLab_seriell.bat

REM --------------------------------------------
REM Flächenbezeichnung --> einmalig!!!
REM --------------------------------------------
REM -->AUSGABE<--: new_model.prt
START call .\linkMASTER\04_linkMASTER_Flaechenbezeichnung.bat

REM --------------------------------------------
REM CalculiX
REM --------------------------------------------
call .\linkMASTER\03_linkMASTER_CalculiX_seriell.bat
:: > test.txt 2>&1

REM --------------------------------------------
REM Auswertungsnetz und verschieben der erzeugten Datein --> in jedem Shot!!! 
REM --------------------------------------------
REM -->AUSGABE<--: elemente_base.txt
REM -->AUSGABE<--: elemente_mod.txt
REM -->AUSGABE<--: fem1.fem
REM -->AUSGABE<--: knoten_base.txt
REM -->AUSGABE<--: knoten_mod.txt
call .\linkMASTER\05_linkMaster_Auswertungsnetz.bat
Zur Erklärung:
1. Da es vorkommen kann, dass bereits zuvor erstellte Dateien vorhanden sind lösche ich diese. Manche verwendeten Programme stürzen sonst ab, da sie nicht überspeichern können.
2. Bei den folgenden zwei Programmen arbeite ich mit START, da diese unabhängig voneinander ausgeführt werden können. Diese Programme erzeugen Dateien, die ich im späteren Verlauf noch brauche.
3. Jetzt kommen wir zu dem Teil "call .\linkMASTER\03_linkMASTER_CalculiX_seriell.bat". Hierbei werden ebenfalls Dateien erzeugt, die das folgende Programm benötigt. Momentan Arbeitet CalculiX (übrigens ein FEM Solver) eine Datei nach der anderen ab, greift dabei aber nur auf einen Kern zurück. Von diesen Dingern habe ich aber 8 Stück, d.h. ich könnte, Reserven eingerechnet, mal mit 4 simultanen Berechnungen arbeiten.
4. Der Rest der Batch soll hier nicht beachtet werden, der funktioniert gut.

UPDATE
Was mir gerade eingefallen ist. Könnte man nicht eine umgebenden FOR-Schleife benützen, wobei die innere For-Schleife immer 4 Rechnungen startet? Allerdings weiß ich dann nicht, wie der Zähler bei Rechnung 5, 9, 13 usw. erkennt, wo er starten soll.
Member: rubberman
Solution rubberman Jul 13, 2014 updated at 13:51:25 (UTC)
Goto Top
Hmm. Wieder ungetestet (logischerweise):
for /d %%i in ("%BASE_DIR%\Run_*") do (  
  if exist "%%~i\Output\2014-07-04_turbine_blade_Mesh.inp" (  
    set "runDir=%%~i"  
    REM Subroutine aufrufen
    call :procRunDir
  ) else (
    echo "%%~i\Output\SOLVER_2014-07-04_turbine_blade.inp" NICHT gefunden  
  )
)

REM Batchdatei beenden (an dieser Stelle laufen aber noch 4 ccx.exe Prozesse weiter)
goto :eof


REM Subroutine
:procRunDir
cd "%runDir%\Output"  
REM ccx.exe asynchron aufrufen
start "" ccx "%runDir%\Output\SOLVER_2014-07-04_turbine_blade"  

REM Warteschleife, solange mehr als 3 Instanzen von ccx.exe parallel laufen
:loop
for /f %%j in ('tasklist /nh /fi "imagename eq ccx.exe" ^| find /i /c "ccx.exe"') do (  
  if %%j gtr 3 (timeout /t 5 /nobreak >nul & goto loop)
)

REM Zum Aufruf der Subroutine in Zeile 5 zurückkehren
goto :eof
Beachte Zeile 11. Wenn die Batchdatei erst beendet werden darf, wenn alle ccx.exe Prozesse abgearbeitet sind, gehört an der Stelle noch eine Warteschleife rein. Weiß ich aber nicht.

Grüße
rubberman
Member: ChocoLoco
ChocoLoco Jul 13, 2014 at 13:54:52 (UTC)
Goto Top
Hammer!!!! face-smile
Ohne von Dir getestet zu sein läuft das Programm einwandfrei. Ich kann Dir gar nicht genug danken!!!!! Das hätte ich in hundert Jahren nicht hinbekommen und spare mir jetzt TAGE(!!!) an Berechnungszeit. Vielen, vielen Dank!


Schöne Grüße und viel Spaß beim WM Finale
ChocoLoco
Member: rubberman
rubberman Jul 13, 2014 at 14:14:18 (UTC)
Goto Top
spare mir jetzt TAGE(!!!) an Berechnungszeit
Automation ist der Sinn von Batchscripten face-wink
Gern geschehen.

Schöne Grüße und viel Spaß beim WM Finale
Dito!
rubberman