Verschieben von Verzeichnisbäumen mit MOVE.exe unter Angabe von mehreren Dateimasken
Der MOVE-Befehl kann nur Dateien aus einem Verzeichnis, ohne die Dateien in den Unterverzeichnissen, verschieben. Außerdem wäre es evtl. noch nützlich, mehrere Dateimasken angeben zu können, um zu bestimmen, welche Dateien verschoben werden.
Hier ein kleiner Batch, der all das erfüllt.
Den Code als rmove.bat speichern, andere Namen sind auch möglich. Der Aufruf sieht dann so aus:
rmove <Quellverzeichnis> <Zielverzeichnis> <Dateimaske1> [<Dateimaske2> ... <DateimaskeX>]
Das Zielverzeichnis muss bereits existieren. Sollte einer der Parameter Leerzeichen enthalten, muss er in Anführungszeichen eingeschlossen werden.
Der Code ruft sich selbst rekursiv auf und erstellt dabei im Zielverzeichnis alle (Unter-)Verzeichnisse aus dem Quellverzeichnis, die Dateien enthalten, auf die die Dateimaske passt.
Ein kleiner Wermutstropfen bleibt: Die Verzeichnisstruktur im Quellverzeichnis bleibt bestehen, auch wenn man *.* als Dateimaske verwendet.
[Edit]
Bzgl. Wermutstropfen: Die Möglichkeit, nach dem Verschieben leere Verzeichnisse zu löschen, ist jetzt eingebaut, laut Posting von Biber (s.u.) jedoch auch gefährlich.
[Edit]
Code wurde nochmal geändert, bei einem Wurzelverzeichnis als Quell- oder Zielverzeichnis hätte es Fehlfunktionen gegeben.
[Edit]
Code wurde zur Geschwindigkeitssteigerung nochmal geändert. Wer den Batch benutzen will, sollte am besten auch die Kommentare entfernen, läuft dann auch schneller.
[Edit]
Code wurde nochmals geändert, damit z.B. & als Teil von Datei-/Verzeichnisnamen kein Problem mehr macht.
Gruß
Friemler
Hier ein kleiner Batch, der all das erfüllt.
@echo off
setlocal
set "prgname=%~0"
set "src=%~1"
set "dest=%~2"
:: evtl. Backslash als letztes Zeichen von src und dest entfernen
if "%src:~-1%"=="\" (
set "src=%src:~0,-1%"
)
if "%dest:~-1%"=="\" (
set "dest=%dest:~0,-1%"
)
:: Die ersten zwei Parameter aus der Parameterliste entfernen
:: Dank an Biber/Bastla/LotPings, von einem habe ich den Trick
set "allparam=%*"
call set "allparam=%%allparam:%1 =%%"
call set "allparam=%%allparam:%2 =%%"
shift
shift
:: Der Call-Befehl wird nur ausgeführt, wenn im
:: Quellverzeichnis Unterverzeichnisse enthalten sind
for /f "delims=" %%p in ('dir "%src%\" /b /-p /a:d 2^>NUL') do (
call "%prgname%" "%src%\%%p" "%dest%\%%p" %allparam%
)
:: Wenn dest ein Wurzelverzeichnis ist, Backslash wieder anhängen
if "%dest:~-1%"==":" (
set "dest=%dest%\"
)
:: Im Quellverzeichnis nach Dateien suchen auf die die Maske passt.
:: Wenn gefunden, Verzeichnis im Ziel anlegen und Dateien verschieben
:loop
set "filesfound=0"
:: Alternative (ohne for-Schleife und filesfound):
:: if exist "%src%\%~1" (
:: md "%dest%" > NUL 2>&1
:: move "%src%\%~1" "%dest%"
:: )
:: erzeugt jedoch eine Fehlermeldung in Verzeichnissen,
:: die nur Unterverzeichnisse und keine Dateien enthalten.
:: Der Code funktioniert trotzdem und ist schneller, aber
:: die Fehlermeldung ist nicht schön.
for /f "delims=" %%f in ('dir "%src%\%~1" /b /-p /a:-d 2^>NUL') do (
set "filesfound=1"
goto break_for
)
:break_for
if "%filesfound%"=="1" (
md "%dest%" > NUL 2>&1
move "%src%\%~1" "%dest%"
)
shift
if not "%~1"== "" goto loop
:: Wenn Quellverzeichnis kein Wurzelverzeichnis ist und
:: keine Dateien oder Verzeichnisse enthält, löschen
if not "%src:~-1%"==":" (
rd "%src%" 2>NUL
)
endlocal
Den Code als rmove.bat speichern, andere Namen sind auch möglich. Der Aufruf sieht dann so aus:
rmove <Quellverzeichnis> <Zielverzeichnis> <Dateimaske1> [<Dateimaske2> ... <DateimaskeX>]
Das Zielverzeichnis muss bereits existieren. Sollte einer der Parameter Leerzeichen enthalten, muss er in Anführungszeichen eingeschlossen werden.
Der Code ruft sich selbst rekursiv auf und erstellt dabei im Zielverzeichnis alle (Unter-)Verzeichnisse aus dem Quellverzeichnis, die Dateien enthalten, auf die die Dateimaske passt.
Ein kleiner Wermutstropfen bleibt: Die Verzeichnisstruktur im Quellverzeichnis bleibt bestehen, auch wenn man *.* als Dateimaske verwendet.
[Edit]
Bzgl. Wermutstropfen: Die Möglichkeit, nach dem Verschieben leere Verzeichnisse zu löschen, ist jetzt eingebaut, laut Posting von Biber (s.u.) jedoch auch gefährlich.
[Edit]
Code wurde nochmal geändert, bei einem Wurzelverzeichnis als Quell- oder Zielverzeichnis hätte es Fehlfunktionen gegeben.
[Edit]
Code wurde zur Geschwindigkeitssteigerung nochmal geändert. Wer den Batch benutzen will, sollte am besten auch die Kommentare entfernen, läuft dann auch schneller.
[Edit]
Code wurde nochmals geändert, damit z.B. & als Teil von Datei-/Verzeichnisnamen kein Problem mehr macht.
Gruß
Friemler
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 147070
Url: https://administrator.de/contentid/147070
Ausgedruckt am: 23.11.2024 um 00:11 Uhr
6 Kommentare
Neuester Kommentar
Moin Friemler,
zu deinem kleinen Wermutstropfen:
Wenn du tatsächlich jemals alle Dateien (also *.*) verschieben wolltest, dann reicht doch ein einfaches MOVE auf das Wurzelverzeichnis.
Ohne irgendein rekursives Geeiere.
Wie du an der letzten Zeile siehst, ist die Struktur "D:\otherwork" wieder vollkommen entsorgt.
In allen anderen Fällen, also wenn ich etwas mit Wildcards verschiebe, z.B. nur *.PDFs...
--> da möchte ich gar nicht, das automatisch irgendwelche Verzeichnisse gelöscht werden, nur weil die grad leer sind.
Vielleicht zeigen auf genau diesen Pfad drei andere Applikationen und bringen mir sonst beim nächsten Start einen Fehler, wenn das Verzeichnis fehlt?
Grüße
Biber
zu deinem kleinen Wermutstropfen:
Wenn du tatsächlich jemals alle Dateien (also *.*) verschieben wolltest, dann reicht doch ein einfaches MOVE auf das Wurzelverzeichnis.
Ohne irgendein rekursives Geeiere.
>dir \work /s /b
D:\work\app
D:\work\dev
D:\work\Dougknox.vbs
D:\work\SQlLoad
D:\work\SQlLoad\S_SLT_MFD_ARTTEXTE.ctl
D:\work\SQlLoad\S_SLT_MFD_ARTTEXTE.xls
(=18:34:43 D:\temp=)
>move d:\work d:\otherwork
1 Datei(en) verschoben.
(=18:35:38 D:\temp=)
>dir \otherwork /s /b
D:\otherwork\app
D:\otherwork\dev
D:\otherwork\Dougknox.vbs
D:\otherwork\SQlLoad
D:\otherwork\SQlLoad\
D:\otherwork\SQlLoad\S_SLT_MFD_ARTTEXTE.ctl
D:\otherwork\SQlLoad\S_SLT_MFD_ARTTEXTE.xls
(=18:35:43 D:\temp=)
>move d:\otherwork d:\work
1 Datei(en) verschoben.
(=18:35:49 D:\temp=)
>dir \otherwork /b /s
Datei nicht gefunden
In allen anderen Fällen, also wenn ich etwas mit Wildcards verschiebe, z.B. nur *.PDFs...
--> da möchte ich gar nicht, das automatisch irgendwelche Verzeichnisse gelöscht werden, nur weil die grad leer sind.
Vielleicht zeigen auf genau diesen Pfad drei andere Applikationen und bringen mir sonst beim nächsten Start einen Fehler, wenn das Verzeichnis fehlt?
Grüße
Biber
Moin,
Naja -wer schreibt, dass es device null sein soll?
oder so ähnlich
Gruß
Zitat von @bastla:
Hallo Friemler!
> :: Der Code funktioniert trotzdem und ist schneller, aber
> :: die Fehlermeldung ist nicht schön.
... und da hilft kein "
Grüße
bastla
Zitat von @Friemler:
Hi bastla,
klar hilft das, aber dann sieht man garkeine Fehlermeldungen mehr.
Hallo Friemler!
> :: Der Code funktioniert trotzdem und ist schneller, aber
> :: die Fehlermeldung ist nicht schön.
... und da hilft kein "
2>nul
"?Grüße
bastla
Zitat von @Friemler:
Hi bastla,
klar hilft das, aber dann sieht man garkeine Fehlermeldungen mehr.
Naja -wer schreibt, dass es device null sein soll?
if exist c:\error.txt del c:\error.txt
keinbefehl>nul 2>>c:\error.txt
if exist c:\error.txt goto error
:code
goto end
:error
type error.txt
:end
Gruß