Batch Ordner umbenennen

Alfredo64

Cadet 3rd Year
Registriert
Jan. 2020
Beiträge
43
Hallo,

Ich bin leider noch sehr am Anfang mit den Umgang im Bezug auf Batch Skripte und muss eine Batch schreiben, dass aus vielen verschiedenen Ordnern immer den selben Ordner raussucht und verschiebt. Allerdings muss der gesuchte Ordner erst umbenannt werden sonst würde er überschrieben werden. Der Ordner soll den Namen des Ordner bekommen in dem Er abgelegt war.

Ich war jetzt so weit, dass ich die Ordner gefunden habe allerdings konnte ich sie nicht umebnen, dass sie sich nicht alle gegenseitig überschreiben.

Ich freue mich über jeden Lösungsvorschlag.
 
Auf welcher Basis wird der Ordner rausgesucht? Anhand des Inhalts oder des Namens?

Ich würde sowas ja eher mit Powershell machen, geht (meiner Meinung nach) einfacher und Powershell ist deutlich moderner/umfangreicher.

mit etwas mehr infos könnte ich dir bei einem Script helfen
 
Dann schreib doch mal, was Du bisher geschrieben hast.

Tip: "move" oder "mv" kann umbenennen und verschieben in einem Schritt.
Verschiebt Dateien und benennt Dateien und Verzeichnisse um.

Um eine oder mehrere Dateien zu verschieben:
MOVE [/Y| /-Y] [Laufwerk:][Pfad]Datei1[,...] Ziel

Um ein Verzeichnis umzubenennen:
MOVE [/Y| /-Y] [Laufwerk:][Pfad]Verz1 Verz2

[Laufwerk:][Pfad]Datei1 Bezeichnet den Pfad und den Namen der zu
verschiebenden Datei(en).
Ziel Bezeichnet den Zielort für die Datei. Das Ziel
kann ein Laufwerkbuchstabe mit Doppelpunkt, ein
Verzeichnisname oder eine Kombination beider sein.
Wenn Sie nur eine einzelne Datei verschieben,
können Sie auch einen Dateinamen angeben, um die
Datei beim Verschieben umzubenennen.
[Laufwerk:][Pfad]Verz1 Bezeichnet das umzubenennende Verzeichnis.
Verz2 Bezeichnet den neuen Namen des Verzeichnisses.
/Y Unterdrückt die Bestätigungsaufforderung zum
Überschreiben bestehender Zieldateien.
/-Y Fordert vor dem Überschreiben bestehender
Zieldateien zur Bestätigung auf.
Die Option /Y ist in der COPYCMD-Umgebungsvariablen eventuell voreingestellt.
Dies kann durch die Option /-Y außer Kraft gesetzt werden. Standardmäßig
müssen Sie das Überschreiben von Dateien bestätigen, es sei denn der MOVE-
Befehl wird von einem Batchprogramm aus aufgerufen.
Ergänzung ()

PvtConker schrieb:
Ich würde sowas ja eher mit Powershell machen,

Ich würd's mit bash oder zsh shellscript machen. Hat eben jeder seine Vorlieben. Batch ist gewünscht.
 
  • Gefällt mir
Reaktionen: Raijin
Alfredo64 schrieb:
Ich war jetzt so weit, dass ich die Ordner gefunden habe allerdings konnte ich sie nicht umebnen, dass sie sich nicht alle gegenseitig überschreiben
Dann teile doch deinen Stand mit uns (in [ code] [/code] tags (ohne Leerzeichen)). Es ist einfacher, dir bei deinem bestehenden Code zu helfen als das Rad komplett neu zu erfinden und dir dann womöglich in einem weiteren Thread zu helfen, diese Lösung in deinen Code zu integrieren... Das gilt insbesondere in deinem Fall, da Ordner verschieben und umbenennen eigentlich bereits mit einem einzigen Befehl abgefrühstückt ist und man sich fragt wo bei dir nun konkret das Problem ist.
 
  • Gefällt mir
Reaktionen: Hayda Ministral
Die Ordner die gesucht werden sollen heißen Zugangsdaten und sollen nach dem Namen gesucht werden. Die Ordner liegen in Ordner die so heißen können: KitKat oder Mars. Und der Zugangsdaten Ordner soll nach dem Verschieben in einen Bestimmten Ordner den bekommen wo er vorher lag. Zum Beispiel: In dem Ordner KitKat liegt ein Ordner Zugangsdaten dieser soll nach NeuerOrdner verschoben werden und von Zugangsdaten auf KitKat benannt werden.
Ergänzung ()

Hallo Raijin,

Mein bis jetzt Funktionierendes Skript ist sehr simple, da wenn ich es verschoben habe es natürlich nicht Funktioniert hat, da es ca. 50 Zugangsdaten Ordner in einen Ordner verschieben würde und somit alles überschreibt. deshalb sollen Die Zugangsdaten Ordner erst nach dem Ordner benannt werden idem sie liegen bevor sie verschoben werden.


Code:
Dir /s /b /ad C:\ZugangsDaten
 
Zuletzt bearbeitet:
Zeig doch einfach deinen bisherigen Batch-Code! Es ist viel einfacher dir bei dem zu helfen was du bisher schon hast.... Ansonsten hat dir @Twostone ja freundlicherweise schon den richtigen Befehl genannt, aber wenn du uns deinen Code nicht zeigst, können wir dir auch nicht vorkauen wie du ihn einbaust....
 
Beispiel in shellscript:
Code:
#!/bin/bash

ARBEITSVERZEICHNIS="/home"
BACKUPPFAD="/backup"

for USERNAME in $(ls ${ARBEITSVERZEICHNIS}); do
   [[ -e "${ARBEITSVERZEICHNIS}/$[USERNAME}/Zugangsdaten" ]] && [[ -d "${ARBEITSVERZEICHNIS}/$[USERNAME}/Zugangsdaten" ]] && mv "${ARBEITSVERZEICHNIS}/$[USERNAME}/Zugangsdaten" "${BACKUPPFAD}/${USERNAME}"
done
exit 0

Voraussetzungen: /home besteht nur aus Verzeichnissen (klar, man kann den ls-Befehl entsprechend erweitern...). Alternativ (wie vor dem edit) kann man der FOR-Schleife auch ein spezifisches Array übergeben, oder den Inhalt einer Textdatei.
 
Zuletzt bearbeitet: (vereinfachung)
Raijin schrieb:
Zeig doch einfach deinen bisherigen Batch-Code! Es ist viel einfacher dir bei dem zu helfen was du bisher schon hast.... Ansonsten hat dir @Twostone ja freundlicherweise schon den richtigen Befehl genannt, aber wenn du uns deinen Code nicht zeigst, können wir dir auch nicht vorkauen wie du ihn einbaust....


ich hatte bis jetzt nur einen kleinen Ansatz hatte mit dem ganzen Thema aber noch nie etwas zu tun. Leider Funktioniert dieser noch nicht:

Code:
Dir /s /b /ad C:\ZugangsDaten do move "C:\Users\lkliegel\Documents\Projekte\Ordner suchen und verschieben\gefundeneOrdner"

Ich hatte gedacht das es so schoben wird allerdings weiß ich nicht wie das mit dem umbenennen Funktionieren soll. Dan Verschieben fertig zu machen hätte ich mir noch zugetraut. Habe leider gar keine Idee wie das mit dem umbenennen gehen soll.

sorry
 
Ok. Du hast einen oder mehrere Ordner, in dem die Nutzerordner liegen. diesen Ordner legst Du in eine Variable, um ihn später einfacher ändern zu können (und Dir Schhreibarbeit zu ersparen).

Gleiches machst Du mit dem Zielpfad.

Dann kannst Du, sofern der Ordner nichts anderes als die Nutzerverzeichnisse enthält, die Ausgabe der Verzeichnisauflistung in ein Array packen und dieses einer FOR-Schleife übergeben, die dann die einzelnen Elemente der Reihe nach durchläuft.

Oder Du gibst die Elemente des Arrays direkt vor. Ersterer Ansatz ist jedoch dynamischer.

Innerhalb der FOR-Schleife schaust Du, ob in der Kombination aus Hauptordner und Nutzerverzeichnis ein Verzeichnis namens "Nutzerdaten" existiert und es auch ein Verzeichnis ist. Wenn ja, übergibst Du das dem MOVE-Befehl und führst mit diesem auch gleichzeitig die Umbenennung durch.

Fertig.
 
Hallo, vielen danke für die ganzen Lösungsvorschläge. Nur leider war die Letze Zeit ziemlich stressig und ich hatte kaum Zeit mich mit diesem Thema zu befassen. Und heute ist eigentlich geplant, dieses Skript einzusetzen. Leider habe ich vorher noch nie so etwas gemacht. Trotzdem wäre es mir am liebsten es, ohne Copy und Paste zu versuchen. Allerdings komme ich mit der Erklärung von dem netten Twostone noch nicht ganz zurecht.

Mein Problem liegt darin, dass ich das mit der for-Schleife nicht verstehe. Wie muss diese aussehen und wie muss ich das mit dem Array machen? Ich finde im Internet alles Mögliche zu schleifen. Aber nichts was mir weiterhilft. Wenn jemand eine kleine Erklärung und ein paar Tipps zur Umsetzung hätte wäre mir sehr geholfen.



Schonmal danke im Voraus für die großartige Hilfe hier.
 
Eine FOR-Schleife ist nichts anderes als eine logische Ausformulierung Deines Vorhabens.

Code:
Für element aus (Listenelement1 Listenelement2); führe aus
   ${Befehl}
fertig

oder eben:

Code:
for ELEMENT in (ELEMENT1 ELEMENT2); do
   ${BEFEHL};
done
exit 0

In diesem Falle wird in jedem Durchlauf ELEMENT durch einen Wert aus dem Array ersetzt, bis das Array komplett abgearbeitet wurde. Im ersten Durchlauf ist also der Wert der Variable ${ELEMENT} "ELEMENT1", beim zweiten "ELEMENT2". dann ist die Schleife beendet, da das Array nur zwei Elemente beinhaltet.
 
Also ich habe jetzt mal angefangen. Und aber immer noch eine Menge Fragen. Das liegt aber nicht an dem Twostone sondern eher an mir glaube ich. Ich habe mal angefangen was zu schreiben nur glaube (bin mir sicher), dass da noch so einiges nicht stimmt. Die stelle die ich als erstes klären wollen würde habe ich im Code markiert.

Code:
for Element in (<#1.Sichpunkt#>); do{

Move-Item -Path C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben -Destination C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben\gefundeneOrdner

Rename-Item -Path C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben -NewName C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben\gefundeneOrdner
}
done

1.Stichpunkt: An der stelle wo ich das in dem Skript markiert habe, habe ich es so verstanden, dass ich dort nur die ganzen Ordner Namen der Ordner einfügen müsste, in denen die Zugangsdaten Ordner liegen und diese Zugangsdatenordner den Namen bekommen, in denen sie liegen.

Allerdings müsste dort ja eigentlich eine Bedingung hatte ich gedacht.
 
Zuletzt bearbeitet:
Alfredo64 schrieb:
An der stelle wo ich das in dem Skript markiert habe, habe ich es so verstanden, dass ich dort nur die ganzen Ordner Namen der Ordner einfügen müsste,

Für so etwas arbeitet man mit Variablen. Siehe #7. Dort habe ich den jeweiligen Ursprungspfad in eine Variable gesetzt. Das kann man natürlich weiter ausführen, wenn man mehrere Ursprungsordner hat, zur Einfachheit habe ich es mal bei einem gelassen.

Die Variable nutze ich anschließend noch einmal zur Ergänzung des Pfades, der dann aus den Variablen Ursprungspfad und Benutzerordner sowie dem festen String "Zugangsdaten" vervollständigt wird. So kann die Schleife alle betreffenden Ordner auch durchlaufen (auch, wenn es sich bei dem Ursprungspfad um ein Array handelt, in diesem Falle würde man zwei Schleifen schachteln).

Eine Bedingung hast Du in dem Sinne nicht mehr, da mv bereits per stat-query den Quellordner aufruft, verschiebt und gleichzeitig umbenennt. Im Beispiel von #7 habe ich allerdings vor die Ausführung des Befehles noch zwei Sicherheitsabfragen gesetzt, damit der Befehl selber keinen Fehler wirft und damit die Schleife unsanft beendet. In dem genannten Falle wird der Befehl erst dann ausgeführt, wenn beide Bedingungen (Ordner existiert und ist ein Verzeichnis) wahr sind.
 
Also ich habe das jetzt so in meinem Kopf, dass es wie folgt Funktionieren soll. Ich habe eine for schleife. Diese brauch immer eine Bedingung die nach jedem Durchlauf erneut abgefragt wird und erst wenn diese nicht mehr erfüllt ist, dann ist es fertig und hört auf.

Wenn das so nicht Funktioniert verbessere mich bitte. Denn mit den zwei schleifen in einander bin ich gerade ein bisschen überfordert. Dann hatten sie noch geschrieben, das der Move (mv) Befehl per stat-query den Quellordner aufruft, verschiebt und umbenennt

Unklar ist mir, wie ich die Bedingung Formulieren soll, und wie dann der Befehl aussieht der in der geschweiften klammer stehen soll. Denn der Befehl soll dann den Zugangsdatenordner verschieben und den Zugangsdatenordner so umbenennen, dass er den selben Namen hat wie der Ordner hieß wo der Zugangsdatenordner lag.

Und das muss für glaube ich 123 Elemente immer wiederholt werden.
Ergänzung ()

Wenn sie der Meinung sind, dass es hier keinen Sinn mehr macht, das jetzt auf der stelle so schnell zu klären, dann ist das verständlich. Falls es so wäre wäre ich nur extrem glücklich, wenn sie mir ein Skript senden würden womit es heute noch durchlaufen würde. Ich interessiere mich zwar dafür allerdings kommen mir langsam Zweifel, dass ich das heute noch schaffe zu verstehen. Und in zwei Wochen bekomme ich eh einen ausführlichen Kurs wo ich es dann denk ich mal eh gezeigt bekomme.

Ich weiß nicht wie sie das sehen ob sie mir lieber ein Skript zusenden oder ob sie mir weiter versuchen nahezubringen wie das Funktioniert. Ich hoffe nur, dass sie jetzt trotzdem noch antworten.
 
Zuletzt bearbeitet:
Alfredo64 schrieb:
Ich habe eine for schleife. Diese brauch immer eine Bedingung die nach jedem Durchlauf erneut abgefragt wird

Eher nicht. Eine FOR-Schleife läuft eine Liste ab. Eine WHILE- oder UNTIL-Schleife braucht eine Bedingung, die bei jeder Iterration erneut abgefragt wird. Eine FOR-Schleife braucht ein Array (eine Liste) mit Elementen, die sie durchläuft und mit jeder Iterration ein Element weiter springt, bis das letzte Element abgelaufen wurde. Dann ist die Schleife regulär beendet.
Ergänzung ()

Alfredo64 schrieb:
wenn sie mir ein Skript senden würden womit es heute noch durchlaufen würde.

Das Script aus #7 wäre unter WSL/WSL2, konkret unter bash bereits lauffähig, nur die Pfadangaben müssten angepasst werden.
 
Twostone schrieb:
Das Script aus #7 wäre unter WSL/WSL2, konkret unter bash bereits lauffähig, nur die Pfadangaben müssten angepasst werden.
OK das Skript verstehe ich allerdings leider noch nicht so ganz. Und ich weiß auch nicht wo ich was einsetzen soll.

Ich habe jetzt auch einfach nochmal was Probiert allerdings kann ich nicht beurteilen ob ich da komplett falsch bin.

Code:
$Ordner = "Schulungen", "Twixxx"

foreach ($Zugangsdaten in C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben\$Ordner){

Move-Item -Path C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben -Destination C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben\gefundeneOrdner

Rename-Item -Path C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben -NewName C:\Users\lkliegel\Documents\Projekte\Ordner_suchen_und_verschieben\gefundeneOrdner
};
done
 
Ah, also zwei Grundordner, die jeweils eigene Nutzerordner enthalten und dann noch einmal Zugangsdaten?
 
Twostone schrieb:
Ah, also zwei Grundordner, die jeweils eigene Nutzerordner enthalten und dann noch einmal Zugangsdaten?

Wollen sie nochmal die Struktur wissen?

die ist wie Folgt: Ich habe einen Ordner Projekte in dem sind 123 Ordner in den 123 Ordner ist immer ein Zugangsdaten Ordner der soll verschoben und so genannt werden wie der Ordner in dem er lag(Das ist dann einer von den 123 Stück).

test111.PNG
 
Also doch recht einfach.

menschliche Logik:

Code:
Für ORDNER aus (Liste der Verzeichnisse im Projektordner); führe aus
  Verschiebe PFAD/ORDNER/Zugangsdaten nach /Zielpfad/ORDNER
fertig

Oder in shellscript:

Code:
#Pfade festlegen
STAMMVERZEICHNIS="/usr/share/Projekte"
ZIELPFAD="/mnt/backup"

#STAMMVERZEICHNIS einlesen und an Variable ORDNERNAME übergeben
for ORDNERNAME in $(ls ${STAMMVERZEICHNIS}); do
#Array ORDNERNAME Element für Element abarbeiten
   #Ordner "Zugangsdaten" in den Zielpfad kopieren und umbenennen in den Namen des Ordners, aus dem es kopiert wurde
   mv ${STAMMVERZEICHNIS}/${ORDNERNAME}/Zugangsdaten ${ZIELPFAD}/${ORDNERNAME}
done
#sauber beenden
exit 0

Sicherheitsabfragen, ob der Ordner auch wirklich existiert und es sich auch wirklich um einen Ordner handelt, wurden hier entfernt.

@Raijin: Hilf mir mal bitte gerade ein wenig aus.
 
Ich sag es vorweg ganz deutlich: BATCH IS A BITCH!

BEVOR du jetzt weiterliest und mein Skript ausprobierst noch ein paar mahnende Worte:

NIEMALS EIN FREMDES SKRIPT BLIND AUF ECHTE DATEN LOSLASSEN BEVOR MAN ES VERSTANDEN HAT!

Erstmal lesen, verstehen und im Zweifelsfalle lieber vorher nachfragen. Die Funktion INITFOLDERS ist Teil eines Testszenarios und löscht beispielsweise den kompletten Quellpfad, wenn sie aufgerufen wird. Auf echte Daten angewandt => PUFF. Deswegen habe ich den Funktionsaufruf sicherheitshalber mit REM auskommentiert. Wenn du das Skript testen willst, das REM in Zeile 10 rausnehmen und dann wird CALL:INITFOLDERS ein Testszenario im Temp-Ordner aufbauen.

Daher gilt: Zu Beginn srcpath und dstpath wie dargestellt im TEMP-Ordner lassen und erstmal das Skript so wie es hier steht testen (wie gesagt, zum Test REM rausnehmen). Wenn alles läuft wie gewünscht, ERST Zeile 10 sowie den kompletten Block INITFOLDERS ganz unten LÖSCHEN. DANACH srcpath, dstpath sowie targetfolder auf deine Daten einstellen.

Code:
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET targetfolder=bla
SET srcpath=%temp%\f1
SET dstpath=%temp%\f2

CLS

REM CALL:INITFOLDERS

DIR /s /ad /b %srcpath%
ECHO.

:SEARCHANDMOVE
PUSHD %srcpath%
FOR /D /r %%A IN (%targetfolder%*) DO (
    CALL:GETPARENTFOLDERNAME %%A
    CALL:GETPARENTFOLDERNAME !parentDir:~0,-1!
    ECHO Found:        %%A
    ECHO Parent:       !parentName!
    ECHO Destination:  %dstpath%\!parentName!
    MOVE %%A %dstpath%\!parentName!
)
POPD

ECHO.
DIR /s /ad /b %dstpath%
GOTO:EOF

:GETPARENTFOLDERNAME
SET parentDir=%~dp1
SET parentName=%~n1
GOTO:EOF



:INITFOLDERS
:: ACHTUNG! REINE TESTFUNKTION! NICHT AUF ECHTE DATEN ANWENDEN!
RMDIR /s /q %srcpath%
RMDIR /s /q %dstpath%

MD %srcpath%\d1\d11\bla
ECHO huhu>%srcpath%\d1\d11\bla\file1
MD %srcpath%\d1\d11\d111
MD %srcpath%\d2\bla
ECHO huhu>%srcpath%\d2\bla\file2
MD %srcpath%\d2\d21
MD %srcpath%\d3\d31\bla
ECHO huhu>%srcpath%\d3\d31\bla\file3
MD %srcpath%\d3\d32\bla
ECHO huhu>%srcpath%\d3\d32\bla\file4
MD %srcpath%\d3\d33\d331\bla
ECHO huhu>%srcpath%\d3\d33\d331\bla\file5
MD %dstpath%
GOTO:EOF

Erklärung zum Skript:

Zunächst muss man targetfolder mit dem Namen des gesuchten Ordners setzen. Anschließend folgen mit srcpath und dstpath der Quell- bzw. Zielpfad. Wichtig: OHNE \ am Ende!

INITFOLDERS ist wie erwähnt lediglich dazu da, das Testszenario aufzubauen. Das vorhandene Szenario wird gelöscht, die Testordner werden neu erzeugt und ein paar Dateien reingeschrieben.
DIESEN BLOCK MUSST DU ENTFERNEN, WENN DU DAS SKRIPT AUF ECHTE DATEN LOSLÄSST!!!!!!!!

Als nächstes listet das Skript den Quellordner samt Unterordner auf.

In der FOR-Schleife passiert nun die Magie. Es werden alle Unterordner im Quellordner gesucht, die auf targetfolder matchen. Eigenheit von Batch: Es MUSS ein Wildcard enthalten sein, also "bla*" und nicht "bla". Das kann im worst case zu einer falschen Erkennung kommen, wenn es neben den gewünschten Ordnern "bla" auch noch "blase" gibt. Ist das der Fall, muss man ggfs das Matching anpassen, um wirklich nur die "bla" Ordner zu bekommen. Die Funktion GETPARENTFOLDERNAME wird notgedrungen zweimal aufgerufen, weil ich keinen anderen Weg gefunden habe, kürzer an den Namen des übergeordneten Ordners zu kommen. Es folgen ein paar ECHOs und zu guter Letzt der Move-Befehl.

Am Ende listet das Skript den Zielordner auf.


Ich betone es nochmal, nicht um irgendwen zu ärgern, sondern um Missverständnisse auszuschließen: VORSICHT!

Es kann übrigens sein, dass man das einfacher, vielleicht sogar viel einfacher programmieren kann. Batch ist aber der letzte Sch.. Ka... Mist auf dieser Erde und selbst banale Dinge sind teilweise absolut unlogisch und müssen völlig krank programmiert werden... batch, eine Hassliebe wie sie im Buche steht ;)
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Twostone und areiland
Zurück
Oben