lprathmann
Goto Top

Nur kopierte Dateien in Datei ausgeben bzw. loggen

Hallo zusammen,

ich habe ein Skript, welches mir bestimmte Dateien kopiert.

Nun habe ich eine weitere Anforderung. Ich möchte die Dateien nur EINMAL kopieren, daher dachte ich, dass ich xcopy /EXCLUDE einsetze.

D.h. über xcopy /exclude:exclude.txt && echo %%i.txt >> exlucde.txt

wobei %%i.txt die gefundenen Text-Dateien sind.

Das funktioniert im Prinzip auch, leider schreibt er aber immer die gefundenen DAteien in die Datei exclude.txt. Ich möchte aber, dass die Dateien nur in die exclude.txt geschrieben werden, wenn die Datei auch kopiert wird, sonst hab ich sie ja zig mal drin stehen.
Hab mit errorlevel experimentiert, aber komme nicht hin (errorlevel ist immer 0).

Beispiel:
1.Durchlauf
3 gefunden Dateien 123456.txt, 234567.txt, 345678.txt
=> sollen kopiert werden
=> Dateinamen sollen zusätzlich in exclude.txt geschrieben werden

2.Durchlauf
3 gefunden Dateien 123456.txt, 234567.txt, 345678.txt (also keine neuen!)
=> sollen nicht kopiert werden (Ausschluss über exclude.txt)
=> Dateinamen sollen NICHT in exclude.txt geschrieben werden

3.Durchlauf
4 gefunden Dateien 123456.txt, 234567.txt, 345678.txt, 456789.txt (also 1 neue!)
=> 456789.txt soll kopiert werden (die anderen Ausschluss über exclude.txt)
=> nur Dateiname 456789.txt sollen in exclude.txt geschrieben werden

Hier mein bisheriger Code (der aber jedesmal in die exclude.txt schreibt):


@Echo off
Set "Base=C:\temp\csv\source"  
Set "Target=C:\temp\csv\target"  
Set "LogFile=exclude.txt"  

pushd %base%

if not exist %LogFile% copy NUL %LogFile%

For /f "delims=" %%i in ('Dir /B/AD /O-D ?????? ^|Findstr "^[0-9][0-9][0-9][0-9][0-9][0-9]$"') Do (   
  if Exist "%%i\Fehler\%%i.txt" xcopy "%%i\Fehler\%%i.txt" %target% /d /exclude:%LogFile% && if %errorlevel% == 0 echo %%i.txt >> %LogFile%  
)


Danke!!

Content-ID: 143213

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

Ausgedruckt am: 25.11.2024 um 21:11 Uhr

Connor1980
Connor1980 20.05.2010 um 12:59:05 Uhr
Goto Top
Sollen die Dateien nur kopiert werden wenn sie verändert wurden bzw. neu sind? Dann wäre es ganz einfach mit
robocopy /MIR 
hinzubekommen.
/MIR
macht einen Spiegel der Quelldateien ins Zielverzeichnis. Es gibt allerdings noch viele weitere Schalter, die dir evtl. behilflich sein könnten. Vllt. hilft dir das weiter.

P.S.: Bitte formatiere deinen Code noch mit den dafür vorgesehenen , s. Formatierungshilfe.
LPRathmann
LPRathmann 20.05.2010 um 13:15:07 Uhr
Goto Top
Wenns geht möchte ich auf "externe" Tools wie Robocopy verzichten (unbestritten der Tatsache, dass Robocopy höchstwahrscheinlich viel geeigneter wäre).

Ich bin ja auch schon relativ weit mit dem Skript, nur noch nicht ganz am Ziel.

Es sollen nur die Dateien, die neu dazugekommen sind, kopiert werden (Änderungen gibt es im Moment nicht).
Im Prinzip macht das ja schon "xcopy /d", aber die Dateien im Zielverzeichnis werden in eine DB importiert und anschließend gelöscht, daher reicht xcopy /d nicht aus, da sonst immer alle Dateien kopiert werden. Daher die Idee mit dem exclude...
Connor1980
Connor1980 20.05.2010 um 13:55:23 Uhr
Goto Top
Unter welchem Betriebssystem arbeitest du denn? robocopy ist von MS und ab Windows 2003 Server und Vista dabei.
Ich hatte eben überlegt das mit einem DIR im Anschluss zu lösen, aber dann hast du ja wesentlich mehr Text um die eigentlichen Dateinamen noch herumschwirren...
LPRathmann
LPRathmann 20.05.2010 um 14:23:58 Uhr
Goto Top
Zitat von @Connor1980:
Unter welchem Betriebssystem arbeitest du denn? robocopy ist von MS und ab Windows 2003 Server und Vista dabei.

Ich glaub Windows 2000 Server, muss aber nochmal nachschauen!

Ich hatte eben überlegt das mit einem DIR im Anschluss zu lösen, aber dann hast du ja wesentlich mehr Text um die
eigentlichen Dateinamen noch herumschwirren...

Kann Dir da jetzt nicht ganz folgen...

Also wenns überhaupt nicht mit Batch gehen sollte und ich zwingend Robocopy verwenden muss, dann wär das zwar schade, aber zuminest ne Aussage...
Wenns doch geht mit Batch, dann bitte ich um Hilfe/Vorschläge
bastla
bastla 20.05.2010 um 18:06:33 Uhr
Goto Top
Hallo LPRathmann!

Abgesehen davon, dass wegen des "&&" das folgende "if %errorlevel% == 0" ohnehin sinnlos ist, kann das innerhalb der Schleife gar nicht wie gewünscht funktionieren (Stichwort "delayedexpansion") - allenfalls wäre noch "if not errorlevel 1" eine Alternative (aber genauso unnötig), daher sollte reichen:
if Exist "%%i\Fehler\%%i.txt" xcopy "%%i\Fehler\%%i.txt" "%target%" /d /exclude:"%LogFile%" && echo %%i.txt>>"%LogFile%"
Was ist eigentlich das genaue Ziel der Aktion? Ein neuerliches Kopieren der bereits im Zielordner vorhandenen Dateien erfolgt ja wegen des "/d" ohnehin nur, wenn die Quelldatei zwischenzeitlich verändert wurde und daher neuer ist; zudem könntest Du ja auch einfach per "if exist" prüfen, ob es die zu kopierende Datei im Zielordner bereits gibt ...

Grüße
bastla
LPRathmann
LPRathmann 20.05.2010 um 19:17:45 Uhr
Goto Top
Zitat von @bastla:

Was ist eigentlich das genaue Ziel der Aktion? Ein neuerliches Kopieren der bereits im Zielordner vorhandenen Dateien erfolgt ja
wegen des "/d" ohnehin nur, wenn die Quelldatei zwischenzeitlich verändert wurde und daher neuer ist; zudem
könntest Du ja auch einfach per "if exist" prüfen, ob es die zu kopierende Datei im Zielordner bereits
gibt ...


Die Dateien werden im Zielordner in eine Datenbank verarbeitet. Nach erfolgreicher Verarbeitung wird die im Zielordner gelöscht, da ansonsten über DB-Logik ebenfalls noch geprüft werden muss was schon verarbeitet ist. Außerdem auch aus Platzgründen sollen die Dateien nach erfolgreicher Verarbeitung in die DB gelöscht werden, daher das ganze...

Bei Deinem Skript werden die Dateien aber doch immer in die Log-Datei geschrieben, unabhängig davon, ob kopiert wird oder nicht. Das möchte ich ja nicht, weil ansonsten die exluce.txt ganz schön groß wird und die Dateinamen redundant drin stehen. (Im Quellverzeichnis wird nie gelöscht)
bastla
bastla 20.05.2010 um 19:51:07 Uhr
Goto Top
Hallo LPRathmann!
Bei Deinem Skript werden die Dateien aber doch immer in die Log-Datei geschrieben, unabhängig davon, ob kopiert wird oder nicht.
Mein Script ist eigentlich zunächst nur eine Korrektur zu Deinem Ansatz - die Abfrage von %errorlevel% in Deiner Version liefert aus zwei Gründen immer 0: Erstens, weil das "&&" vorweg schon den Errorlevel checkt und nur, wenn dieser 0 ist (also "xcopy" ohne Fehler beendet wurde), den Rest der Zeile ausführt, und zweitens, weil innerhalb der Schleife %errorlevel% immer den Wert liefert, der bereits vor der Schleife enthalten war (gilt auch für andere Variable, wenn keine "delayedExpansion" verwendet wird).
Wenn ich das richtig verstehe sollen also alle Dateien also nur genau einmal kopiert werden (unabhängig davon, ob sie nachträglich noch verändert wurden) - in diesem Fall würde ich das (ungetestet) so versuchen:
@echo off & setlocal
Set "Base=C:\temp\csv\source"  
Set "Target=C:\temp\csv\target"  
Set "LogFile=exclude.txt"  

pushd %base%
if not exist %LogFile% copy NUL %LogFile%

for /f "delims=" %%i in ('Dir /B/AD /O-D ?????? ^|Findstr "^[0-9][0-9][0-9][0-9][0-9][0-9]$"') Do (   
  if exist "%%i\Fehler\%%i.txt" findstr /i /x /c:"%%i.txt" "%LogFile%" || (copy "%%i\Fehler\%%i.txt" %target% >nul && >>"%LogFile%" echo %%i.txt)  
)
popd
Grüße
bastla
LPRathmann
LPRathmann 21.05.2010 um 09:16:44 Uhr
Goto Top
Hallo bastla,

danke für die Antwort.
Genau im Moment ist es so, dass es nur neue Dateien geben kann, keine Änderungen daran. (wenn doch ist das dann das Kriterium für Robocopy?)

Ich habe Dein Skript mal probiert, leider funktioniert es noch nicht so wie gewünscht:

1. Ausführung (keine DAteien im Zielverzeichnis; 3 Dateien im Quellverzeichnis);

=> Die Dateien werden kopiert, die Dateinamen in das Logfile eingetragen (3 Einträge). Bis hierher sieht alles gut aus.

2. Ausführung (3 Dateien im Zielverzeichnis; 3 Dateien im Quellverzeichnis);

=> Kopiert wird nichts (richtig), aber leider wandern wieder die Dateinamen in das Logfile, das dann 6 Einträge hat...

Was mir noch aufgefallen ist, dass das Skript leider langsam ist. Dies liegt vermutlich an der Volltextsuche und dass für jede Datei in das Logfile geschaut werden muss? Bei sehr vielen Dateien im Quellverzeichnis wäre das vermutlich sher langsam...
...was jetzt aber kein Vorwurf sein soll face-smile
Bisher muss ich davon ausgehen, dass die Dateien im Zielverzeichnis nach Verarbeitung gelöscht werden müssen.
Ein xcopy /D war deutlich schneller...aber erfordert eben, dass die Dateien im Zielverzeichnis nicht gelöscht werden....

Oder gibt es noch andere Ansätze für mein Problem?

Aber erstmal würde ich gerne das Skript oben lauffähig machen (@bastla: mit Deiner Hilfe face-smile )
LPRathmann
LPRathmann 21.05.2010 um 09:51:27 Uhr
Goto Top
Hallo bastla,

es geht jetzt. Das /x bei findstr war schuld. Wenn ich das weglasse, dann gehts:

@echo off & setlocal

Set "Base=C:\temp\csv\source"   
Set "Target=C:\temp\csv\target"   
Set "LogFile=exclude.txt"   

pushd %base%

REM Log- und Exclude-Datei erstellen, falls nicht vorhanden
if not exist %LogFile% copy NUL %LogFile%

REM 6stellige mit exclude test
For /f "delims=" %%i in ('Dir /B/AD /O-D ?????? ^|Findstr "^[0-9][0-9][0-9][0-9][0-9][0-9]$"') Do (   
	if Exist "%%i\Fehler\%%i.txt" findstr /i "%%i.txt" "%LogFile%" || ( copy "%%i\Fehler\%%i.txt" %target% >nul && >>"%LogFile%" echo %%i.txt )  
)

popd
bastla
bastla 21.05.2010 um 10:11:06 Uhr
Goto Top
Hallo LPRathmann!
Das /x bei findstr war schuld
Du hast ja fixe Namensstrukturen (6 Zeichen numerisch) und kannst daher tatsächlich darauf verzichten, da nicht zu befürchten ist, dass ein Teilstring als Treffer gewertet wird (weil zB "11333.txt" in "111333.txt" enthalten wäre); trotzdem funktioniert bei meinem (inzwischen vorgenommenen Test) auch der Vergleich der kompletten Zeile ...
Da "/d" als Schalter für "xcopy" nicht in Frage kommt: Könnte ev das "Archiv"-Attribut genutzt werden, bzw anders formuliert: Werden die Dateien, nachdem sie einmal kopiert wurden, noch verändert? Falls es keine Veränderung gibt (und das Script vor dem täglichen Backup, welches vermutlich das Archivbit zurücksetzt, ausgeführt wird), wäre ein
xcopy /m ...
eine Alternative ...
[Edit]
Um aber auch Deinen ursprünglichen Plan nochmals aufzugreifen:
xcopy "%%i\Fehler\%%i.txt" "%target%\" /y /exclude:"%LogFile%" >>"%LogFile%"
sollte auch klappen - wenn es auch hässlich ist, bei jedem (versuchten) Kopiervorgang einen Eintrag der Art
1 Datei(en) kopiert
zu erhalten (zum Wegfiltern wäre allerdings schon wieder einn "find" oder "findstr" nötig, also etwa:
xcopy "%%i\Fehler\%%i.txt" "%target%\" /y /exclude:"%LogFile%"|findstr /v /c:"Datei(en) kopiert" >>"%LogFile%"
[/Edit]

Grüße
bastla
LPRathmann
LPRathmann 21.05.2010 um 11:22:46 Uhr
Goto Top
Hallo bastla,

ich muss noch einen Fehler von mir korrigieren: Dein Skript funktioniert natürlich auch mit findstr /x

Ich hatte dummerweise beim schreiben in das Logfile " ... echo %%i.txt )" geschrieben => mit einem Leerzeichen vor der schließenden Klammer, daher waren die Einträge in der Logfile z.B. "123456.txt " und somit konnte die Suche "123456.txt" nicht funktionieren...

face-smile

Deine anderen Vorschläge probier ich jetzt auch mal...danke mal schon soweit!!

[Edit]

Zitat von @bastla:
Da "/d" als Schalter für "xcopy" nicht in Frage kommt: Könnte ev das "Archiv"-Attribut
genutzt werden, bzw anders formuliert: Werden die Dateien, nachdem sie einmal kopiert wurden, noch verändert? Falls es keine
Veränderung gibt (und das Script vor dem täglichen Backup, welches vermutlich das Archivbit zurücksetzt,
ausgeführt wird), wäre ein
xcopy /m ...
> 
eine Alternative ...

Hierzu braucht man aber Schreibrechte im Zielordner, richtig?

[/Edit]
bastla
bastla 21.05.2010 um 12:46:24 Uhr
Goto Top
Hallo LPRathmann!
Hierzu braucht man aber Schreibrechte im Zielordner, richtig?
Im Quellordner aber auch face-wink (sollte "Attribute schreiben" sein) ...

Grüße
bastla
LPRathmann
LPRathmann 21.05.2010 um 13:21:49 Uhr
Goto Top
Hallo bastla,

im Quellordner ist klar face-smile
Im Zielordner könnte es aber für mich durchaus sein, dass ich keine Schreibrechte habe.
Ich habe jetzt übrigens alle 3 Methoden zum Laufen bekommen. Vielen Dank für Deine Hilfe!!!