golsin
Goto Top

Dateien kopieren, rekursiv in einen Ordner

Hallo und noch ein Frohes neues Jahr face-wink
Ich bin mal wieder etwas ratlos...

Ich Versuche von einem Rechner aus, in einer Freigabe nach einem Ordner zu suchen und dessen Inhalt auf einen anderen Rechner zu kopieren.
Zuvor hatte ich alles lokal auf meinen PC erfolgreich getestet, als ich es dann aber mit UNC Pfaden probiert habe kam das Script anscheinend ins stolpern und konnte die Dateien nicht mehr kopieren.
Leider fällt mir keine Lösung für das Problem ein, ich hoffe das mir jemand von euch helfen kann.

Ein Aufruf des Scripts sieht bei mir folgendermaßen aus:
file.bat "\\pc1\pfad\zum\durchsuchen" "\\pc2\kopiere\hier\hin" datei_filter  


Das Script ist ursprünglich von Biber, ich habe es dann versucht auf meine Bedürfnisse anzupassen.
Quelle: Administrator.de
@echo off & setlocal
Set source=
Set target=

Set source=%1
Set source=%source:~1,-1%
Set target=%2
Set target=%target:~1,-1%
echo. -------------------------------------------
:: %3 Ist der Filter fur den Ordner
echo. Erster Parameter:  %1 
echo. Zweiter Parameter: %2 Edit: %target%
echo. Dritter Parameter: %3 (Filter)
echo. -------------------------------------------

Pushd "%source%" && Rem In das Source-Verzeichnis wechseln  
echo VERARBEITUNG: Versuche erste FOR (Push in "%source%")  

REM Die aussere For-Schleife...Fur alle Unterverzeichnisse unterhalb %source%...
FOR /F "delims=" %%i IN ('dir /A:D /b /s %3*') DO (  
    echo Erstes FOR: Directory [%%i]
		REM Zweite For-Schleife...Fur alle Dateien im jeweiligen Unterverzeichnis
		PushD "%%i"	  
		FOR /F "delims=" %%a in ('dir /b /A:-d ^2^>nul') do (  
		  REM Das "^2^>nul" unterdruckt die Meldung "Datei nicht gefunden",  
		  REM ...Wenn mal ein leeres Unterverzeichnis dabei sein sollte.
		  REM ---------------------------------------------------------
		  REM nachste Datei anzeigen mit vollem Pfad und Namen
		  echo ...... ["%source%%%~nxa"]  
		  IF not exist "%target%\%%~nxa" (  
		 @echo d| xcopy /Y /R /H /V "%source%\%%~nxa" "%target%\%%~nxa"  
		  ) 
		)
		PopD
		set dirtoremove=%%i
		set dirtoremove=%dirtoremove:~3,0%
		echo. %dirtoremove%
		echo. rmdir /S /Q "%source%\%dirtoremove%"  
	)
    PopD
)
PopD
goto :eof

Gruß Golsin

Content-Key: 260071

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

Ausgedruckt am: 29.03.2024 um 07:03 Uhr

Mitglied: Marabunta
Marabunta 16.01.2015 um 12:52:39 Uhr
Goto Top
ein einzeiler mit robocopy hilft nicht?
robocopy "SOURCE" "DESTINATION" Filter nach Bedarf...
Mitglied: golsin
golsin 16.01.2015 um 15:42:11 Uhr
Goto Top
Das wäre eine Idee, ich probiere das mal aus.
Dankeschön!
Mitglied: golsin
golsin 19.01.2015 um 10:17:10 Uhr
Goto Top
Das klappt alles soweit schon super, nur noch eine kleine letzte Frage.
Wie bringe ich robocopy dazu keine Ordner mit zu kopieren?

So wie ich das gelesen habe sollte "/MOV" nur Dateien und "/MOVE" Dateien und Ordner kopieren.
Bei mir werden jedoch auch die Ordner mit kopiert in denen die zu kopierenden Dateien liegen.
Ich brauche die Dateien zwingend in dem Zielordner ohne Unterordner um von dort weiter arbeiten zu können.

Wie du vorgeschlagen hast, hier der Einzeiler:
robocopy /MOV "\\server1\freigabe1\quell_ordner" "\\server2\freigabe2\ziel_ordner" filter_dateien* /S  
Mitglied: Marabunta
Marabunta 19.01.2015, aktualisiert am 20.01.2015 um 16:01:34 Uhr
Goto Top
da habe ich wohl etwas falsch verstanden. Robocopy kann soweit ich weiß höchstens die Dateien der obersten Ebene kopieren, aber rekursiv ohne die Verzeichnisstruktur abzubilden nicht. Diese Lösung in Powershell sollte funktionieren:

Als Beispiel werden nur dateien mit *.jpg kopiert
$quelle = "\\server1\freigabe1\quell_ordner"  
$ziel= "\\server2\freigabe2\ziel_ordner"  

get-childitem $quelle -recurse | foreach{
if($_.PSIsContainer -ne $true){
copy-item $_.fullname -Destination $ziel  -include "*.jpg"   
}
}
Mitglied: golsin
golsin 20.01.2015 um 15:07:08 Uhr
Goto Top
So langsam wird es hakelig
Trotzdem schon mal vielen dank für deine Hilfe!

Das Programm was das Script ansteuern soll beherrscht kann dies nur mit Batch Dateien. ='(
Also einmal über Batch das Powershell Script anstoßen:
1. Batch:
@echo off
set PowerShellScriptPath=%4
PowerShell -NoProfile -ExecutionPolicy Bypass -Command "& '%PowerShellScriptPath%' '%1' '%2' '%3'";  

Zuvor habe ich bei der Batch nach einem Ordner gesucht der einem Filter entsprach und daraus alle Dateien kopiert, bei dem Script was du mir netterweise zur Verfügung gestellt hast, wird nur nach Datei Namen gesucht.
Das ist für mich aber hinderlich, da der Inhalt in dem Ordner, der zu kopieren ist, nicht immer namentlich gleich ist.

2. Powershell:
$quelle = $args
$ziel = $args[1]
$filter = $args[2]

get-childitem $quelle*$filter* -recurse | foreach{
if($_.PSIsContainer -ne $true){
copy-item $_.fullname -Destination $ziel -include "*"   
}
}

Beim testen jedoch bekomme ich schon beim ausführen schon Probleme

PS C:\Windows\system32> "C:\mv_out_of_folder_v3.ps1" "\\pc\TEST\Ordner" "\\pc\TEST2\Ordner" "666666"  
Unerwartetes Token "\\pc\TEST\Ordner" im Ausdruck oder in der Anweisung.  
Bei Zeile:1 Zeichen:50
+ "C:\mv_out_of_folder_v3.ps1" "\\pc\TEST\Ordner" <<<<  "\\pc\TEST2\Ordner" "666666"  
    + CategoryInfo          : ParserError: (\\pc27\TEST\Ordner:String) , ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

Das ist so ziemlich das erste was ich in Richtung PS angehe, ich bin also für jeden netten Tipp offen ;)
Mitglied: Marabunta
Lösung Marabunta 20.01.2015, aktualisiert am 22.01.2015 um 16:58:46 Uhr
Goto Top
versuch es mal mit punkt am anfang: ."C:\mv_out_of_folder_v3.ps1" "\\pc\TEST\Ordner" "\\pc\TEST2\Ordner" "666666"
Was du gemacht hast ist quasi nur textausgabe gewesen, der zweite pfad(text) in der Zeile hat ihn schon umgehauen.

Ich hab den Filter jetzt in where-object reingemacht. Damit kann auch der Ordner gefiltert werden.(geht bestimmt irgendwie besser aber ich komm nicht drauf =/)

Mit diesem Skript, falls z.B. nach "Test" gefiltert wird, werden alle Dateien unterhalb "\\pc\TEST\" gefunden, weil im Pfad "Test" vorkommt.

$quelle = $args
$ziel = $args[1]
$filter = $args[2]

get-childitem $quelle -recurse | Where-Object {$_.Fullname -match $filter} |
foreach{
if($_.PSIsContainer -ne $true)
{
copy-item $_.fullname -Destination $ziel 
$letztedatei=$_.fullname #das ist nur für die anzeige in der letzten zeile
}
}
get-Childitem $letztedatei |select * #hier wird einiges über die datei angezeigt, damit lässt sich ein filter leichter zusammenbauen.
z.B. $_.Basename um nur im Dateinamen selbst zu filtern etc.
Mitglied: golsin
golsin 21.01.2015 um 10:53:54 Uhr
Goto Top
Aaaaaaah,
die Ausgabe von den Datei Infos mich weiter gebracht, Dankeschön!

$quelle = $args
$ziel = $args[1]
$filter = $args[2]

get-childitem $quelle -recurse | Where-Object {$_.DirectoryName -match $filter} |
	foreach{
		if($_.PSIsContainer -ne $true)
		{
		copy-item $_.fullname -Destination $ziel
		}
	}
get-childitem $quelle -recurse | Where-Object {$_.PSPath -match $filter} | rm -recurse

Stellt sich mir nur noch die Frage ob das löschen des nun nicht mehr benötigtem Quellunterordner eleganter gelöst werden kann ;)

Sehe ich das richtig, dass ich mit einem
-and
zusätzliche Objektdefinitionen angeben kann?
Also:
Where-Object {$_.Fullname -match $filter -and $_.PSPath -match 'blablabla' -and ......}
Mitglied: Marabunta
Lösung Marabunta 21.01.2015, aktualisiert am 22.01.2015 um 16:58:52 Uhr
Goto Top
ja s.u. da wird es auch verwendet.
du könntest nach copy-item auch remove-item $_.fullname machen, damit ist der quellordner am ende leer.
die jetzt leeren ordner können hiermit gelöscht werden(script ergoogelt und leicht angepasst):

$EmptyFolders = Get-ChildItem -Path $quelle |
Where-Object {$_.PSIsContainer -eq $true -and (Get-ChildItem -Path $_.FullName -Recurse) -eq $null} #also wenn es ein leerer ordner ist....
$EmptyFolders | Remove-Item

das entspricht schon fast dem was du hast.
Mitglied: golsin
golsin 22.01.2015, aktualisiert am 23.01.2015 um 09:30:56 Uhr
Goto Top
So hatte ich das anfangs auch, den Ordner leeren und später alle leeren Ordner löschen.
Es kam mir nur etwas doppelt gemoppelt vor, weswegen ich auch nochmal nach einer eleganteren Lösung gefragt hatte.

Schlussendlich funktioniert es aber so wie ich mir das gedacht habe!

Vielen dank für deine freundliche Unterstützung!!