Musterlösungen: Dateien verschieben abhängig vom Teil des Dateinamens
Ich habe eine ständig wachsende Anzahl von Dateien aus unterschiedlichen Quellen, die in Unterverzeichnisse verschoben werden sollen. So weit so einfach.
Die Herkunft der Dateien ist aus einem Anfangsstring unterschiedlicher Länge erkennbar, dann kommt ein eindeutiger Separator und dann weitere Dateiangaben. Die Dateien sollen in ein Unterverzeichnis (das ggf. noch nicht existiert) und dem Part des Dateinamens entspricht, der vor dem Separator kommt.
Beispiel:
1 m1234__20160309.log
2 m1234__20160308.log
3 m34xl2__0900-20160308.avi
4 m34xl2__20160308.txt
5 n890__tv21000.jpg
Datei 1 und 2 in Verzeichnis m1234
Datei 3 und 4 in Verzeichnis m34xl2
Datei 5 im Optimalfall nicht verschieben (da nur eine Datei mit Anfang n890 existiert), oder ohne Prüfung ins Verzeichnis n890.
Die einfache Variante extrahiert also den vorderen Teil einer Datei und verschiebt die Datei dann in ein Unterverzeichnis, das heißt wie der extrahierte Teil.
Die Optimalvariante prüft quasi auf "Teildubletten" und verschiebt nur die, und lässt die Einzelfälle aus.
Ich habe die Hilfe durchsucht und auch gegoorgelt, aber immer nur Varainten gefunden, bei denen der Anfang zumindest von der Länge her gleich war, das ist hier aber nicht der Fall.
Vielleicht weiß hier ja jemand, wie man das am einfachsten machen kann.
Danke
Die Herkunft der Dateien ist aus einem Anfangsstring unterschiedlicher Länge erkennbar, dann kommt ein eindeutiger Separator und dann weitere Dateiangaben. Die Dateien sollen in ein Unterverzeichnis (das ggf. noch nicht existiert) und dem Part des Dateinamens entspricht, der vor dem Separator kommt.
Beispiel:
1 m1234__20160309.log
2 m1234__20160308.log
3 m34xl2__0900-20160308.avi
4 m34xl2__20160308.txt
5 n890__tv21000.jpg
Datei 1 und 2 in Verzeichnis m1234
Datei 3 und 4 in Verzeichnis m34xl2
Datei 5 im Optimalfall nicht verschieben (da nur eine Datei mit Anfang n890 existiert), oder ohne Prüfung ins Verzeichnis n890.
Die einfache Variante extrahiert also den vorderen Teil einer Datei und verschiebt die Datei dann in ein Unterverzeichnis, das heißt wie der extrahierte Teil.
Die Optimalvariante prüft quasi auf "Teildubletten" und verschiebt nur die, und lässt die Einzelfälle aus.
Ich habe die Hilfe durchsucht und auch gegoorgelt, aber immer nur Varainten gefunden, bei denen der Anfang zumindest von der Länge her gleich war, das ist hier aber nicht der Fall.
Vielleicht weiß hier ja jemand, wie man das am einfachsten machen kann.
Danke
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 298655
Url: https://administrator.de/contentid/298655
Ausgedruckt am: 05.11.2024 um 20:11 Uhr
17 Kommentare
Neuester Kommentar
Moin.
Powershell z.B.
Gruß jodel32
Powershell z.B.
# Alle Dateien des Ordners nach dem ersten Teil des Dateinamens gruppieren (wird über Regular Expressions und Group-Matching gemacht). dann werden nur die Gruppen verschoben von denen es mindestens 2 Dateien gibt
gci "C:\quellordner\*.*" | group {[regex]::match($_.Basename,'^(.*?)__').Groups[1].Value} | ?{$_.Count -ge 2} | %{
# Zielordner der Gruppe festlegen
$targetfolder = "C:\quellordner\$($_.Name)"
# wenn Zielordner noch nicht existiert erstelle ihn
if(!(Test-path $targetfolder)){md $targetfolder}
# Alle Dateien der Gruppe in den Zielordner verschieben
move-item $_.Group -Destination $targetfolder -Force
}
gegoorgelt
Hoffentlich auch ordentlich ausgespuckt Gruß jodel32
Hallo Hopfman und willkommen im Forum!
Als Batch schematisch etwa so:
Wenn Du Dateien, die verschoben werden, angezeigt haben möchtest, lass am Ende der Zeile 9 "
Grüße
bastla
Als Batch schematisch etwa so:
@echo off & setlocal
set "Ordner=D:\Dein Ordner"
pushd "%Ordner%"
for /f "delims=" %%i in ('dir /b *_*') do (
for /f "delims=_" %%a in ("%%i") do (
for /f %%n in ('dir "%%a_*.*"2^>nul^|findstr "Datei(en)"') do if %%n gtr 1 (
md "%%a" 2>nul
move "%%a_*.*" "%%a">nul
)
)
)
popd
>nul
" weg.Grüße
bastla
Nabend,
Powershell:
Edit: @114757 mal wieder schneller unterwegs mit der Powershell als ich; und dazu noch kürzer
Powershell:
# Gibt den Quellpfad der Dateien an
$source = "C:\test"
# Schreibt alle Dateien auf der obersten Ebene in ein Array
$files = gci $source | ?{$_.Mode -eq '-a---'}
foreach ($f in $files){
# Spaltet den String an einer beliebigen Stelle auf, an der der Separator vorhanden ist
$dublette = $f -split '__'
# Zähler, wie häufig das erste Element vorhanden ist
$counter = $files -match $dublette
# Definieren des Zielpfades
$destpath = $source +"\" +$dublette
# Wenn eine Dublette vorhanden ist und das Verzeichnis noch nicht vorhanden ist, wird es erstellt und alle Dateien mit diesem Schema werden dorthin verschoben
if ( $counter.Count -gt 1){
$search = Test-Path $destpath
if ($search -eq $false){
New-Item $destpath -ItemType directory
}
Move-Item $source\$f -Destination $destpath
}
}
Edit: @114757 mal wieder schneller unterwegs mit der Powershell als ich; und dazu noch kürzer
[OT]
Moin alle,
na kommt, jetzt noch einen (vorzugsweise kommentierten) VBS-Schnipsel dazu, dann mach ich einen "Tipp" aus den ganzen Musterlösungen.
Und lass ihn als Referenz für künftige verzweifelte GoorglerInnen stehen.
Ich warte....
Grüße
Biber
P.S. An manchen Tagen ist es mir eine Freude, im Bereich "Entwicklung" mitzulesen.
[/OT]
Moin alle,
na kommt, jetzt noch einen (vorzugsweise kommentierten) VBS-Schnipsel dazu, dann mach ich einen "Tipp" aus den ganzen Musterlösungen.
Und lass ihn als Referenz für künftige verzweifelte GoorglerInnen stehen.
Ich warte....
Grüße
Biber
P.S. An manchen Tagen ist es mir eine Freude, im Bereich "Entwicklung" mitzulesen.
[/OT]
Zitat von @Biber:
na kommt, jetzt noch einen (vorzugsweise kommentierten) VBS-Schnipsel dazu, dann mach ich einen "Tipp" aus den ganzen Musterlösungen.
Kann ich leider nicht mit dienen na kommt, jetzt noch einen (vorzugsweise kommentierten) VBS-Schnipsel dazu, dann mach ich einen "Tipp" aus den ganzen Musterlösungen.
Und lass ihn als Referenz für künftige verzweifelte GoorglerInnen stehen.
Soll man für den Lern-Effekt den Code kommentieren?Edit: Lesen sollte man nochmal üben -.-
P.S. An manchen Tagen ist es mir eine Freude, im Bereich "Entwicklung" mitzulesen.
Warum das?Zitat von @Hopfman:
Vielen lieben Dank, perfekt!
Und während ich bastlas batch noch einigermaßen verstehe, wird Powershell für mich immer ein Buch mit 7 Siegeln bleiben...
och, ist eig. wesentlich einfacher als Batch.Vielen lieben Dank, perfekt!
Und während ich bastlas batch noch einigermaßen verstehe, wird Powershell für mich immer ein Buch mit 7 Siegeln bleiben...
Magst du den Thread dann noch als gelöst markieren?
Hallo Hopfman!
Wenn der Separator mehrere Zeichen umfasst, müsste der Batch anders gestaltet werden - ansonsten lässt sich aber zumindest mit einer Variablen die Anpassung vereinfachen (auf speziellen Wunsch ausnahmsweise sogar mit Kommentaren ):
Grüße
bastla
P.S.: Als unkommentierte (und nur oberflächlich getestete) Draufgabe auch noch die Variante mit erweitertem Separator:
P.P.S.: @ Biber
Als VBS braucht das (wegen der Dateizählung - ein Pendant zu
Wenn der Separator mehrere Zeichen umfasst, müsste der Batch anders gestaltet werden - ansonsten lässt sich aber zumindest mit einer Variablen die Anpassung vereinfachen (auf speziellen Wunsch ausnahmsweise sogar mit Kommentaren ):
@echo off & setlocal
set "Ordner=D:\Dein Ordner"
set "Separator=_"
REM voruebergehend in den angegebenen Ordner wechseln
pushd "%Ordner%"
REM in einer Schleife alle passenden Dateien (mit dem Separator im Namen; keine Ordner) abarbeiten
for /f "delims=" %%i in ('dir /b/a-d "*%Separator%*"') do (
REM Anfangsstring isolieren
for /f "delims=%Separator%" %%a in ("%%i") do (
REM Anzahl der mit dem Anfangsstring beginnenden Dateien ermitteln und
REM wenn mehr als eine Datei vorhanden ist ...
for /f %%n in ('dir "%%a%Separator%*.*"2^>nul^|findstr "Datei(en)"') do if %%n gtr 1 (
REM ... den Zielordner erstellen (falls bereits vorhanden Fehlermeldung nicht anzeigen) ...
md "%%a" 2>nul
REM ... und alle entsprechenden Dateien in den Zielordner verschieben
move "%%a%Separator%*.*" "%%a">nul
)
)
)
REM Wechsel des Ordners rückgängig machen
popd
bastla
P.S.: Als unkommentierte (und nur oberflächlich getestete) Draufgabe auch noch die Variante mit erweitertem Separator:
@echo off & setlocal
set "Ordner=D:\Dein Ordner"
set "Separator= - "
pushd "%Ordner%"
for /f "delims=" %%i in ('dir /b/a-d "*%Separator%*"') do (
set "Name=%%~ni"
setlocal enabledelayedexpansion
call set "Anfang=%%Name:%Separator%!Name:*%Separator%=!=%%"
for /f %%n in ('dir "!Anfang!%Separator%*.*"2^>nul^|findstr "Datei(en)"') do if %%n gtr 1 (
md "!Anfang!" 2>nul
move "!Anfang!%Separator%*.*" "!Anfang!">nul
)
endlocal
)
)
popd
P.P.S.: @ Biber
Als VBS braucht das (wegen der Dateizählung - ein Pendant zu
dir "* - *.*"
gibt es mE ja leider nicht) ewig :Ordner = "D:\Dein Ordner"
Separator = " - "
Set fso = CreateObject("Scripting.FileSystemObject")
For Each File In fso.GetFolder(Ordner).Files
If InStr(File.Name, Separator) > 0 Then
Anfang = Split(File.Name, Separator)(0)
L = Len(Anfang & Separator)
Anzahl = 0
For Each Testfile In fso.GetFolder(Ordner).Files
If LCase(Left(TestFile.Name, L)) = LCase(Anfang & Separator) Then Anzahl = Anzahl + 1
Next
If Anzahl > 1 Then
Ziel = Ordner & "\" & Anfang
If Not fso.FolderExists(Ziel) Then fso.CreateFolder(Ziel)
fso.MoveFile Ordner & "\" & Anfang & Separator & "*", Ziel & "\"
End If
End If
Next
[OT ii]
Moin alle,
ich danke nochmals euch unermüdlichen Skriptern und ändere diese "Frage" mal zu einem "Tipp" um.
Denn ich denke, diese Muster-Skizzen werden auch noch anderen hilfreich sein.
Zum der ewigen Kontroverse "Kommentieren von Code" vs "Mein Schnipsel ist doch selbsterklärend"...
ich sach ma' so.... ich schreibe am liebsten Oneliner... da gehe ich der Diskussion aus dem Weg.
Was immer für eine Kommentierung spricht: wenn es ganz blöd läuft, dann muss auch ich mal einen mehrzeiligen Schnipsel anpassen....
Aber dreieinhalb Jahre, nachdem ich ihn mal flüssig runtergetippt habe (sofern ich meine Tastaturfertigkeiten als flüssiges Tippen bezeichnen kann), brauche ich erstmal ein paar Minuten, um überhaupt nachzuvollziehen, WTF ich mir denn dabei gedacht habe.
Andererseits...
Ich liebe auch selbstdokumentierenden Code und "sprechende Variablen" wie
Aber was soll's... Unsere Kantine dokumentiert auch nicht jede Zutat im Nudelauflauf.
Grüße
Biber
[/OT ii]
.
Moin alle,
ich danke nochmals euch unermüdlichen Skriptern und ändere diese "Frage" mal zu einem "Tipp" um.
Denn ich denke, diese Muster-Skizzen werden auch noch anderen hilfreich sein.
Zum der ewigen Kontroverse "Kommentieren von Code" vs "Mein Schnipsel ist doch selbsterklärend"...
ich sach ma' so.... ich schreibe am liebsten Oneliner... da gehe ich der Diskussion aus dem Weg.
Was immer für eine Kommentierung spricht: wenn es ganz blöd läuft, dann muss auch ich mal einen mehrzeiligen Schnipsel anpassen....
Aber dreieinhalb Jahre, nachdem ich ihn mal flüssig runtergetippt habe (sofern ich meine Tastaturfertigkeiten als flüssiges Tippen bezeichnen kann), brauche ich erstmal ein paar Minuten, um überhaupt nachzuvollziehen, WTF ich mir denn dabei gedacht habe.
Andererseits...
Ich liebe auch selbstdokumentierenden Code und "sprechende Variablen" wie
strDayOfWeek = 42;
. Vor allem, wenn ich so einen "geerbten" Schnipsel mal warten muss.Aber was soll's... Unsere Kantine dokumentiert auch nicht jede Zutat im Nudelauflauf.
Grüße
Biber
[/OT ii]
.
Ein gutes hat das weglassen der Doku hier aber manchmal, die Leute sind gezwungen sich damit auseinanderzusetzen, statt oft nur copy n' paste zu betreiben, ist zwar für den TO etwas mehr Aufwand aber auch das kann einen positiven Lerneffekt für den TO bedeuten
Ist zwar bei Powershell Onlinern etwas aufwendiger zu dokumentieren, da man einen Roman vor die Zeile schreibt, aber dem guten Willen habe ich die Zeilen oben auch noch nachträglich kommentiert.
Aber ich sehs schon voraus wenn wir auf den Beitrag hier verweisen, kommt zu 95% wieder die Antwort von den meisten:
"Aber bei mir ist das doch ganz anders ?"
Ist zwar bei Powershell Onlinern etwas aufwendiger zu dokumentieren, da man einen Roman vor die Zeile schreibt, aber dem guten Willen habe ich die Zeilen oben auch noch nachträglich kommentiert.
Aber ich sehs schon voraus wenn wir auf den Beitrag hier verweisen, kommt zu 95% wieder die Antwort von den meisten:
"Aber bei mir ist das doch ganz anders ?"
Hallo Bastla,
vielen Dank für diese Lösung. Mein Problem ist ähnlich: Das Kriterium bei mir ist der Teil nach dem Unterstrich.
Z.B:
Original Ordner:
Berta_PC01.txt
Berta_PC02.txt
Berta_PC03.txt
Thomas_PC01.txt
Thomas_PC02.txt
Thomas_PC03.txt
Ziel:
Ordner PC01:
Berta_PC01.txt
Thomas_PC01.txt
Ordner PC02:
Berta_PC02.txt
Thomas_PC02.txt
Deine Lösung sortiert und verschiebt nach dem ersten Teil des Dateinamens.
Ich habe versucht das zu ändern, ohne Erfolg.
Danke und viele Grüße
Thomas
vielen Dank für diese Lösung. Mein Problem ist ähnlich: Das Kriterium bei mir ist der Teil nach dem Unterstrich.
Z.B:
Original Ordner:
Berta_PC01.txt
Berta_PC02.txt
Berta_PC03.txt
Thomas_PC01.txt
Thomas_PC02.txt
Thomas_PC03.txt
Ziel:
Ordner PC01:
Berta_PC01.txt
Thomas_PC01.txt
Ordner PC02:
Berta_PC02.txt
Thomas_PC02.txt
Deine Lösung sortiert und verschiebt nach dem ersten Teil des Dateinamens.
Ich habe versucht das zu ändern, ohne Erfolg.
Danke und viele Grüße
Thomas
Hallo tomcruise!
Versuch es damit (vüllig ungetestet):
Grüße
bastla
Versuch es damit (vüllig ungetestet):
@echo off & setlocal
set "Ordner=D:\Dein Ordner"
set "Separator=_"
REM voruebergehend in den angegebenen Ordner wechseln
pushd "%Ordner%"
REM in einer Schleife alle passenden Dateien (mit dem Separator im Namen; keine Ordner) abarbeiten
for /f "delims=" %%i in ('dir /b/a-d "*%Separator%*"') do (
REM 2. String isolieren
for /f "tokens=2 delims=%Separator%" %%a in ("%%i") do (
REM Anzahl der mit dem String endendem Dateien ermitteln und
REM wenn mehr als eine Datei vorhanden ist ...
for /f %%n in ('dir "*%Separator%%%a.*"2^>nul^|findstr "Datei(en)"') do if %%n gtr 1 (
REM ... den Zielordner erstellen (Name des Ordners ohne Typ, zB ".txt") -
REM (falls bereits vorhanden, Fehlermeldung nicht anzeigen) ...
md "%%~na" 2>nul
REM ... und alle entsprechenden Dateien in den Zielordner verschieben
move "*%Separator%%%a" "%%~na">nul
)
)
)
REM Wechsel des Ordners rückgängig machen
popd
bastla
Batch mit Separator funktioniert wunderbar mit Dateien. Danke hier für die Mühe. Leider komme ich nicht weiter, aufgrund von Unwissenheit, aus diesem Script etwas zu basteln, dass auch nur für Ordner funktioniert.
Sprich: Alle Ordner samt Inhalt, bis zu einem bestimmten Separator in den Ordner legen, der nach dem Teil bis zum Separator benannt wird oder vllt. verständlicher
Guck im Ordnernamen bis zum Seperator, erstelle einen Ordner benannt nach dem Teil bis zum Separator und verschiebe Ordner inklusive Inhalt in den neuen Ordner. Wenn Ordner bereits vorhanden, dann verschiebe in den vorhandenen Ordner.
Beispiel:
(1)Ordner var1_var2_separator1_var3
verschieben in Ordner var1_var2
Ordner var1_var2_separator1_var4
verschieben in den bereits vorhandenen Ordner var1_var2
(2)Ordner var1_separator1_var2
verschieben in Ordner var1
usw.
Ich bedanke mich im Voraus für die Unterstützung.
Sprich: Alle Ordner samt Inhalt, bis zu einem bestimmten Separator in den Ordner legen, der nach dem Teil bis zum Separator benannt wird oder vllt. verständlicher
Guck im Ordnernamen bis zum Seperator, erstelle einen Ordner benannt nach dem Teil bis zum Separator und verschiebe Ordner inklusive Inhalt in den neuen Ordner. Wenn Ordner bereits vorhanden, dann verschiebe in den vorhandenen Ordner.
Beispiel:
(1)Ordner var1_var2_separator1_var3
verschieben in Ordner var1_var2
Ordner var1_var2_separator1_var4
verschieben in den bereits vorhandenen Ordner var1_var2
(2)Ordner var1_separator1_var2
verschieben in Ordner var1
usw.
Ich bedanke mich im Voraus für die Unterstützung.