weaslflink
Goto Top

Dateien in verschiedene Ordner kopieren

Hallo liebe Community,

Ich bin auf dem Gebiet von Batch ein totaler Neuling und kenn mich überhaupt nicht aus.
Deswegen bitte ich euch um Rat.

Nun zu meinem Problem.

Ich möchte via Batch Dateien auf ein anderes Laufwerk in verschiedene Ordner kopieren. Falls die Datei schon vorhanden ist soll diese im namen eweitert werden, sodass ich beide Dateien behalte.

Die Dateinamen sehen wie folgt aus:
3413_13354789.pdf
20501_55568749.pdf
4403_....
etc.

Ausgangsorder ist der windows "eigene dateien/myscans/" ordner und ziellaufwerk ein usb-stick.

Auf dem USB-Stick sind jeweis Ordner mit der mit der Bezeichnung "3413", "20501","4403" etc.

Also, ich möchte alle Dateien, die mit der Zahl vor dem Unterstrich anfangen, in den jeweils dazugehörigen Ordner verschieben. Falls dieser noch nicht existiert soll einer erstellt werden.

Ich hoffe ich habe mein Vorhaben verständnisvoll geschildert.

Vielen Dank schon mal im voraus !

Content-Key: 177759

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

Printed on: April 16, 2024 at 23:04 o'clock

Member: bastla
bastla Dec 15, 2011 at 15:13:25 (UTC)
Goto Top
Hallo weaslflink und willkommen im Forum!

Ohne Berücksichtigung bereits vorhandener Dateien im Zielordner würde sich das in einer Zeile abhandeln lassen (ungetestet zur Direkteingabe in CMD, daher nur mit %i und nicht, wie in einem Batch, mit %%i; das "echo" vor dem "xcopy" sorgt für ein gefahrloses Testen, da so der Kopierbefehl nur angezeigt, aber nicht ausgeführt wird; Ziellaufwerk E: ):
for /f "tokens=1* delims=_" %i in ('dir /b /a-d "%userprofile%\Eigene Dateien\myscans\*_*.pdf"') do @echo xcopy "%userprofile%\Eigene Dateien\myscans\%i_%j" "E:\%i\%i_%j*"
Falls die Datei schon vorhanden ist soll diese im namen eweitert werden, sodass ich beide Dateien behalte.
solltest Du noch etwas näher ausführen ...

Grüße
bastla

[Edit] Fehlendes Anführungszeichen nach pdf ergänzt [/Edit]
Member: Friemler
Friemler Dec 15, 2011 at 17:13:10 (UTC)
Goto Top
Hallo weaslflink,

hier mein Vorschlag zur Lösung des Problems:
@echo off & setlocal

set "SrcDir=%UserProfile%\Eigene Dateien\myscans"  
set "DestDir=E:"  
set "FileType=pdf"  

for /f "tokens=1* delims=_" %%a in ('dir /b /a:-d "%SrcDir%\*_*.%FileType%" 2^>NUL') do (  
  call :RenOldVersion "%DestDir%\%%a\%%a_%%b"  
  xcopy "%SrcDir%\%%a_%%b" "%DestDir%\%%a\%%a_%%b*" > NUL  
)

exit /b


:RenOldVersion
  set /a "NumFiles=0"  

  for /f "tokens=1 delims=:" %%c in ('dir /b /a:-d "%~dpn1*%~x1" 2^>NUL ^| findstr /n "^"') do (  
    set /a "NumFiles=%%c"  
  )

  if %NumFiles% gtr 0 ren "%~1" "%~n1(%NumFiles%)%~x1"  
exit /b

In den Zeilen 3-5 musst Du die Pfade ggf. anpassen. Dabei gilt zu beachten, dass keiner der beiden Pfade in Zeile 3 und 4 mit einem \ (Backslash) enden darf. Im Beispielcode oben würden die Zielverzeichnisse 3413, 20501, 4403 etc. im Wurzelverzeichnis von Laufwerk E: gesucht.

Falls im Zielverzeichnis bereits Dateien vorhanden sind, die umbenannt werden müssen, geht das Script nach Art des Windows Explorers vor und hängt eine in Klammern stehende Zahl an den Dateinamen an (aus 3413_13354789.pdf wird z.B. 3413_13354789(1).pdf oder 3413_13354789(2).pdf). Die Zahl hängt von der Anzahl bereits existierender Versionen der Datei ab. Erledigt wird das ganze im Unterprogramm RenOldVersion.

Gruß
Friemler


[EDIT]
Ich habe die Anregung von bastla aufgegriffen, und das Nicht-Vorhanden-Sein des Zielverzeichnisses im Script berücksichtigt (wird durch die Verwendung von XCOPY bei Bedarf angelegt).
[/EDIT]

[EDIT2]
Außerdem auch von mir noch eine Erklärung zur Funktionsweise des Unterprogramms RenOldVersion (das Hauptprogramm baut auf bastlas ursprünglichem Code auf und lässt sich deshalb mit Hilfe seiner ausführlichen Erklärung verstehen):

Dem Unterprogramm wird in Zeile 8 der Zielpfad+Name der aktuell betrachteten Quelldatei als Parameter übergeben. Im Unterprogramm kann er über %1 (der erste Parameter) angesprochen werden.

Mit %~dpn1 in Zeile 18 wird der Parameter in Laufwerk (d) + Pfad (p) + Dateiname (n) ohne Dateierweiterung zerlegt (aus E:\PDF-Dokumente\3413_13354789.pdf wird E:\PDF-Dokumente\3413_13354789). Dem wird ein * angehängt (damit vom DIR-Befehl auch schon existierende Dateien mit einer in Klammern eingeschlossenen Laufnummer gefunden werden). Daran wird mit %~x1 die Dateierweiterung (also .pdf) angehängt.

Die somit erzeugte Dateimaske wird dem DIR-Befehl übergeben, der wegen dem Parameter /a:-d nur Dateien findet und wegen dem Parameter /b nur eine Liste mit deren Namen ohne Pfad und ohne den üblichen Header und Footer der DIR-Ausgabe erzeugt. Falls der Pfad nicht bzw. keine passende Datei existiert, würde DIR eine Fehlermeldung ausgeben, was dazu führen würde, dass der Code innerhalb der FOR-Schleife fälschlicherweise ausgeführt wird. Deshalb wird mit 2^>NUL der Fehlerkanal zum NUL-Device umgeleitet, die Fehlermeldung wird somit verschluckt und der Schleifenrumpf nicht ausgeführt (das Zirkumflex-Zeichen ^ in 2^>NUL ist nur an dieser Stelle, im Kopf der FOR-Schleife, erforderlich, um das >-Zeichen zu "escapen").

Die Ausgabe von DIR wird wegen ^| (auch hier dient das ^ zum "escapen" von |) über eine Pipe an den Befehl FINDSTR weitergeleitet, der wegen dem Parameter "^" (ein sog. regulärer Ausdruck) Zeilen mit einem Anfang findet (also alle Zeilen) und wegen /n Zeilennummern mit einem nachfolgenden Doppelpunkt vor jede Zeile schreibt.

Der Doppelpunkt ist mit delims=: für die FOR-Schleife als Trennzeichen innerhalb einer Zeile definiert. Wegen tokens=1 wird nur der Teil des Zeileninhalts an die Laufvariable %%c zugewiesen, der vor dem Doppelpunkt steht, also die Zeilennummer, die von FINDSTR erzeugt wurde.

Innrhalb der FOR-Schleife wird diese Zeilenummer bei jedem Durchlauf an die Variable NumFiles zugewiesen. Nach dem Abschluss der Schleife enthält NumFiles also die Anzahl der Dateien, auf die das Suchmuster passt oder (wegen Zeile 16) den wert 0, wenn es keine solchen Dateien gibt.

In Zeile 22 wird geprüft, ob der Wert von NumFiles größer 0 ist, wenn ja wird die gefundene Datei mit REN umbenannt.

Der ursprüngliche Name steht in der Variablen %1 (die Tilde ~ in "%~1" entfernt evtl. vorhandene Anführungszeichen, in die der Inhalt von %1 eingeschlossen sein könnte; außerdem wird damit der Inhalt von %1 auf jeden Fall mit Anführungszeichen eingeschlossen; hier nicht unbedingt notwendig, ist aber eine Angewohnheit von mir, solche Dinge zu coden), der neue Name wird mit %~n1(%NumFiles%)%~x1 erzeugt (%~n1 liefert den Dateinamen ohne Dateierweiterung, daran wird mit (%NumFiles%) die in Klammern eingeschlossene Laufnummer und mit %~x1 die Dateierweiterung angehängt).

Mit exit /b in Zeile 23 wird zum Hauptprogramm zurückgesprungen.
[/EDIT2]
Member: weaslflink
weaslflink Dec 15, 2011 at 17:14:08 (UTC)
Goto Top
Vielen Dank für deine schnelle Antwort. Habe es auch direkt ausprobiert (als als bat mit zwei %%) jedoch ohne Erfolg.

Könntest du vielleicht zu den einzelnen Schritten kurz erklären was diese bewirken ?


Falls die Datei, nehmen wir mal "20501_55568749.pdf" schon vorhanden ist soll wie in windows diese so umbenannt werden "20501_55568749 (2).pdf"
Member: weaslflink
weaslflink Dec 15, 2011 at 17:18:53 (UTC)
Goto Top
Vielen Dank Friemler,

ich werde es morgen ausprobieren und direkt resummee geben.
Member: bastla
bastla Dec 15, 2011 at 18:37:51 (UTC)
Goto Top
Hallo weaslflink!
Habe es auch direkt ausprobiert (als als bat mit zwei %%) jedoch ohne Erfolg.
Wenn Du es nochmals (und jetzt auch mit dem inzwischen oben nachgetragenen fehlenden Anführungszeichen) versuchst, sollte es klappen ...

Zur gewünschten Erklärung:
for /f "tokens=1* delims=_" %i in
trennt die in weiterer Folge erzeugten Zeilen anhand des ersten "_", sodass in %i der Teil davor und in %j der Teil danach steht (sollten noch weitere "_" enthalten sein, bleiben diese erhalten, da wegen des "*" in "1*" keine weitere Zerlegung vorgenommen wird).
('dir /b /a-d "%userprofile%\Eigene Dateien\myscans\*_*.pdf"')
erzeugt wegen "/a-d" ein Inhaltsverzeichnis nur von Dateien, nicht auch von Ordnern, welch ev ebenfalls dem Suchmuster "*_*.pdf" entsprechen würden und gibt (wegen "/b") als einzige Information je Datei nur deren Namen + Typ aus (zur Zerlegung wie oben besprochen).
do @echo xcopy "%userprofile%\Eigene Dateien\myscans\%i_%j" "E:\%i\%i_%j*"
Da sich jetzt in %i und %j die benötigten Namensteile befinden, können diese für das Kopieren nach Wunsch zusammengesetzt werden - für die Datei "3413_13354789.pdf" wäre demnach %i=3413 und %j=13354789.pdf und daraus ergäbe sich der Befehl
@echo xcopy "%userprofile%\Eigene Dateien\myscans\3413_13354789.pdf" "E:\3413\3413_13354789.pdf*"
Die Verwendung von "xcopy" hat den Vorteil, dass bei Bedarf der Zielordner erstellt wird. Nachteilig wäre die Nachfrage
Ist das Ziel E:\3413\3413_13354789.pdf ein Dateiname
oder ein Verzeichnisname
(D = Datei, V = Verzeichnis)?
welche nicht mit einem Schalter analog zu "/I" (womit festgelegt wird, dass das Ziel ein Verzeichnis sein soll) verhindert werden kann - daher der Trick mit dem angefügten "*" (der könnte nicht am Ende eines Verzeichnisnamens verwendet werden, daher muss das Ziel eine Datei sein).
Was das ev erforderliche Umbenennen angeht, hat Friemler ja schon einen Vorschlag unterbreitet (wobei ich allerdings eher die bereits vorhandenen Dateien unverändert lassen und der neu zu kopierenden Datei die Laufnummer hinzufügen würde) ...

Grüße
bastla
Member: bastla
bastla Dec 15, 2011 at 19:02:15 (UTC)
Goto Top
@Friemler
Dein Ansatz berücksichtig (noch) nicht, dass der Zielordner ev erst erstellt werden muss ...

Grüße
bastla
Member: Friemler
Friemler Dec 15, 2011 at 20:56:06 (UTC)
Goto Top
Hallo bastla,

Zitat von @bastla:
Dein Ansatz berücksichtig (noch) nicht, dass der Zielordner ev erst erstellt werden muss ...

da Du dafür schon einen schönen Trick präsentiert hast (danke, wieder was gelernt face-smile ), habe ich ihn kurzerhand in mein Script eingebaut.

Btr. "Umbenennen der alten Versionen": Meine Methode hat den Vorteil, dass die aktuelle Version der Datei zu jeder Zeit den gleichen Namen hat. Somit ist es einfacher, aus anderen Scripten/Programmen darauf Bezug zu nehmen. Was letztendlich besser ist, kommt auch auf die (vom TO nicht näher erläuterten) Anforderungen an.

Gruß
Friemler
Member: bastla
bastla Dec 15, 2011 at 21:16:57 (UTC)
Goto Top
Hallo Friemler!
Meine Methode hat den Vorteil, dass die aktuelle Version der Datei zu jeder Zeit den gleichen Namen hat.
ACK - allerdings wäre das dann genau genommen nicht mehr die "Art des Windows Explorers" ...

... aber das muss sich letztlich der TO überlegen ...

Grüße
bastla
Member: weaslflink
weaslflink Dec 16, 2011 at 07:11:54 (UTC)
Goto Top
Guten Morgen.

And dieser Stelle nochmal danke für eure bemühungen.

Habe den Code nun ausprobiert. Das CMD öffnet sich, schließt sich jedoch dann direkt wieder.
Was mache ich denn falsch ? Kann ich irgendwie über das Script ein debugger modus laufen lassen ?

[Edit]
also ich habe mal das "exit /b" aus der Mitte entfernt und vor dem am ende ein "pause" gesetzt. Jetzt kommt er schon weiter aber ich poste euch mal was ich bekomme:

C:\Users\pzhqch\Documents\My Scans\test>set "SrcDir=C:\Users\pzhqch\Eigene Datei  
en\myscans\test"  

C:\Users\pzhqch\Documents\My Scans\test>set "DestDir=C:\Users\pzhqch\Eigene Date  
ien\myscans\test2"  

C:\Users\pzhqch\Documents\My Scans\test>set "FileType=pdf"  

C:\Users\pzhqch\Documents\My Scans\test>for /F "tokens=1* delims=_" %a in ('dir  
/b /a:-d "C:\Users\pzhqch\Eigene Dateien\myscans\test\*_*.pdf" 2>NUL') do (  
call :RenOldVersion "C:\Users\pzhqch\Eigene Dateien\myscans\test2\%a\%a_%b"  
 xcopy "C:\Users\pzhqch\Eigene Dateien\myscans\test\%a_%b" "C:\Users\pzhqch\Eige  
ne Dateien\myscans\test2\%a\%a_%b*"   1>NUL  
)

C:\Users\pzhqch\Documents\My Scans\test>set /a "NumFiles=0"  

C:\Users\pzhqch\Documents\My Scans\test>for /F "tokens=1 delims=:" %c in ('dir /  
b /a:-d "*" 2>NUL | findstr /n "^"') do (set /a "NumFiles=%c"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=1"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=2"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=3"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=4"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=5"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=6"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=7"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=8"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=9"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=10"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=11"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=12"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=13"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=14"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=15"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=16"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=17"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=18"  )  

C:\Users\pzhqch\Documents\My Scans\test>(set /a "NumFiles=19"  )  

C:\Users\pzhqch\Documents\My Scans\test>if 19 GTR 0 ren "" "(19)"  
Das System kann die angegebene Datei nicht finden.

C:\Users\pzhqch\Documents\My Scans\test>pause
Drücken Sie eine beliebige Taste . . .
Nach drücken der Taste schließt sich das fenster.

Habe die Batch datei im Ordner "test" und dort sind 18 pdf files drin zum testen der batch

Ich hoffe euch hilft das weiter
Member: bastla
bastla Dec 16, 2011 at 07:45:02 (UTC)
Goto Top
Hallo weaslflink!

Wenn ich
C:\Users\pzhqch\Documents\My Scans\test>set "SrcDir=C:\Users\pzhqch\Eigene Dateien\myscans\test"
betrachte (was mir mit der passenden leichter fällt face-wink), bin ich mir nicht so ganz sicher, dass der Quellpfad
C:\Users\pzhqch\Eigene Dateien\myscans\test
lauten sollte ...

Grüße
bastla
Member: weaslflink
weaslflink Dec 16, 2011 at 08:21:39 (UTC)
Goto Top
ah das war der kleine Übeltäter face-big-smile

habe es gemacht mit:
%userprofile%\Documents\My Scans\test

und siehe da es funktioniert face-smile

Jetzt habe ich aber noch eine Frage. Abe erst mal zu dem Hintergrund. Ich scanne momentan Dokumente so ca 50-70 Stk am Tag und vergebe denen eine Namen wie oben schon erwähnt. Jetzt kommt es auch oft vor das diese doppelt sind. D.h das ich im Scan-Ordner schon dateien habe mit Namen
3376_55582593(2)
3376_55582593(3)

wenn ich diese mit hilfe des tools kopiere dann wird aus
3376_55582593(2)
3376_55582593(2)(1)

Ist es machbar das die datei nicht in ...(2)(1) umbenannt wird sondern in ...(3) wenn diese jedoch auch schon vergeben ist dann ind ...(4) usw. Ich hoffe Ihr habt verstanden was ich meine. So wirdh nämlich später von dem Projekt jeweils das aktuellste mit der höchsten Zahl angezeigt.


Wenn ich das jetzt richtig verstanden habe dann müsste das doch so klappen, dass im Hauptordner Dateien die ein "([Zahl]).pdf" am Ende haben diese vor dem kopieren entfernt und dann erst in den Ziel kopiert wird.
Würde das so gehen ?


Ich danke für eure Hilfe
Member: bastla
bastla Dec 16, 2011 at 23:03:05 (UTC)
Goto Top
Hallo weaslflink!

Wenn sicher gestellt ist, dass nur der Dateiname vor einer ev ersten Klammer benötigt wird, dann (weitgehend ungetestet) etwa so:
@echo off & setlocal
set "SrcDir=%userprofile%\Documents\My Scans\test"  
set "DestDir=%userprofile%\Documents\My Scans\test2"  
set "FileType=pdf"  

for /f "tokens=1* delims=_" %%a in ('dir /b /a-d "%SrcDir%\*_*.%FileType%" 2^>NUL') do (  
  for /f "delims=(" %%i in ("%%~nb") do call :Kopieren "%SrcDir%\%%a_%%b" "%%a" "%%i" "%%~xb"  
)
exit /b

:Kopieren
set /a "NumFiles=0"  
for /f "tokens=1 delims=:" %%c in ('dir /b /a-d "%DestDir%\%~2\%~2_%~3*%~4" 2^>NUL ^| findstr /n "^"') do set /a "NumFiles=%%c"  
set /a NumFiles+=1
if %NumFiles% gtr 1 (
    xcopy %1 "%DestDir%\%~2\%~2_%~3(%NumFiles%)%~4*"  
) else (
    xcopy %1 "%DestDir%\%~2\%~2_%~3%~4*"  
)
exit /b
Eine Alternative zu den Zeilen 12 und 13 könnte übrigens so aussehen:
for /f %%c in ('dir /b /a-d "%DestDir%\%~2\%~2_%~3*%~4" 2^>NUL ^|find /c /v "?"') do set /a "NumFiles=%%c"
Grüße
bastla
Member: Biber
Biber Dec 31, 2011 at 15:20:06 (UTC)
Goto Top
Moin weaslflink,

Zitat von @weaslflink:
Ich danke für eure Hilfe
Wärest du bereit, diesen Dank für die weniger lesefähigen in diesem Forum zu visualisieren, vorzugsweise in diesem dezenten Wacholderton?
Brennesselfarben ginge zur Not auch....

Grüße
Biber
Member: weaslflink
weaslflink Jan 02, 2012 at 06:32:28 (UTC)
Goto Top
[image]http://www.tippy.de/ecards/motive/danke.jpg[/image]

Hiermit bedanke ich mich herzlich für die großartige Unterstützung die ich von allen erhalten habe !