Bestimmte Dateitypen aus Unterordnern in einen gemeinsamen Ordner kopieren / verschieben

1147
WraythOsu

Situation:

Zahlreiche Unterordner mit zufälligen Ordnernamen, die mehrere Dateien mit zufälligen Namen enthalten. Einige möchte ich behalten, andere können gelöscht werden.

Tor:

Verschieben Sie die Dateien mit den Erweiterungen: * .exe * .pdf * .avi oder anderen angegebenen Erweiterungen aus den Unterordnern in einen gemeinsamen separaten Ordner, ohne die vorherige Ordnerstruktur neu zu erstellen. Damit habe ich nur einen Ordner mit den Dateien, die ich möchte, und hinterlasse andere Dateitypen. Dann protokollieren Sie die Verzeichnisnamen des Unterordners (results-log.log) und löschen Sie die Unterordner und den gesamten Inhalt.

Beispiel; beginnend:

  • parent1
    • sub1
      • random1.exe
      • random2.pdf
      • random3.txt
    • 2
      • random4.exe
      • random5.avi
      • random6.log
      • random7.jpg

Endresultat:

  • parent2
    • Ergebnisprotokoll.log
    • random1.exe
    • random2.pdf
    • random4.exe
    • random5.avi

Ich habe also nach anderen Antworten gesucht und es sieht so aus, als ob ich eine FOR-Schleife brauche, aber ich verstehe nicht genug, wie das mit Parametern funktioniert, um das zu tun, was ich brauche. Das Verschieben von PDF-Dateien in einen übergeordneten Ordner aus einem Unterordner mit Variablennamen ist ein Beispiel, das ich mir angesehen habe, und ich habe mir die vorgeschlagenen Informationen angesehen, aber ich kann nicht verstehen, wie die Parameter und Variablen funktionieren. Besonders dort, wo ich mehrere Dateitypen abdecken muss.

Bisher schaue ich so etwas an:

@ECHO OFF SETLOCAL EnableExtensions set "_parent=c:\logs\cache\" set "_dest=c:\archive\" for /D /r %%G in ("%_parent%\*") do ( if exist "%%~G\*.pdf" ( echo move /B "%%~G\*.pdf" "%_dest%\" ) else ( echo nothing to copy "%%~G\*.pdf" "%_parent%\" ) ) 
  • Zeile 3: Ich glaube, dass "c: \ logs \ cache \" als übergeordneter Ordner festgelegt wird. In meinem Beispiel dazu wäre dies "parent1".
  • Zeile 4 sollte das Ziel für den Ordner "parent2" als "c: \ archive" festlegen.
  • Zeile 5 ist %%Grichtig? Ist es wichtig, was der Brief ist?
  • Zeile 6 Wie kann ich die anderen Dateierweiterungen angeben, nach denen ich suchen möchte?
  • Zeile 7 möchte ich verwenden moveoder etwas anderes und was ist der /BParameter? /yist der einzige, den ich kenne move.

Hoffentlich reichen die Infos aus und können nach Bedarf für weitere Informationen editieren.

2

1 Antwort auf die Frage

3
mrfreester

Alles was Sie tun müssen, ist mehrere ifAussagen zu machen, denke ich. In Ihrer Schleife würde es so aussehen:

IF exist "%%G\*.pdf" ( move /Y "%%G\*.pdf" "%_dest%\" echo %%G>>"%_dest%\results-log.log )  IF exist "%%G\*.exe" ( move /Y "%%G\*.exe" "%_dest%\" echo %%G>>"%_dest%\results-log.log ) IF exist "%%G\*.avi" ( move /Y "%%G\*.avi" "%_dest%\" echo %%G>>"%_dest%\results-log.log ) 

Wenn Sie möchten, dass die Nachricht nichts verschiebt, können Sie immer eine Variable setzen, wenn sie in eine dieser IFAnweisungen gerät und überprüfen, ob sie gesetzt ist.

Ich bin nicht sicher, was /Bist, das sieht für mich nicht richtig aus. Ich denke, du hast recht mit /y.

Das Gkann ein beliebiges Zeichen sein, aber es kann nicht mehr als ein Zeichen sein. Gist was normalerweise verwendet wird.

Ich würde vorschlagen, nach solchen Powershell-Skripten zu suchen. Meiner Meinung nach ist es sauberer und einfacher, solche Dinge mit weniger Codezeilen auszuführen. Möglicherweise gibt es einen Befehl zum Verschieben aller Dateien mit mehreren Erweiterungen gleichzeitig. Ich verstehe jedoch, dass in den meisten DOS-Versionen normalerweise keine Syntax zum Verschieben verfügbar ist.

BEARBEITEN:

Ich habe dies lokal getestet und es scheint zu funktionieren, was Sie tun. Sie müssen es für Ihren speziellen Fall anpassen.

@ECHO OFF SETLOCAL EnableExtensions enabledelayedexpansion set _parent=c:\logs\cache\ set _dest=c:\archive\ set found=0  for /R %_parent% %%G in (.) do ( set found=0 IF exist "%%G\*.pdf" ( move /Y "%%G\*.pdf" "%_dest%\" set found=1 ) IF exist "%%G\*.exe" ( move /Y "%%G\*.exe" "%_dest%\" set found=1 ) IF exist "%%G\*.avi" ( move /Y "%%G\*.avi" "%_dest%\" set found=1 )  IF !found!==1 ( rd /s /q "%%G" echo %%G>>"%_dest%\results-log.log" ) )  endlocal 

Wenn Sie die /DOption in der forSchleife verwenden, wird das aktuelle Verzeichnis, in dem Sie das Skript ausführen, an die %%GVariable angehängt, die meiner Meinung nach nicht das ist, was Sie wollen. Die Art und Weise, wie ich sie oben geschrieben habe, besagt im Wesentlichen, dass alle Ordner im übergeordneten Verzeichnis rekursiert und %%Gauf diesen Speicherort gesetzt werden (.).

Sie müssen auch das hinzufügen, enabledelayedexpansiondamit Sie die foundVariable in verschiedenen Blöcken verwenden können. Dann müssen Sie sie aufrufen, !found!anstatt sie %found%zu verwenden. Nur eine seltsame Art von Batch-Scripting.

Wenn Ihnen diese Syntax wirklich komisch vorkommt, sind Sie nicht alleine. Sie müssen nur nachforschen und Ihre eigenen Tests durchführen, um zu sehen, was passiert, bis Sie das bekommen, was Sie wollen. Wenn Sie in Powershell einsteigen, werden Sie hoffentlich das Debuggen mit Powershell-ISE und die verwendete Syntax viel einfacher finden.

Ich habe nicht alle diese Syntax getestet, aber es sollte Ihnen zumindest nahe kommen, was Sie brauchen. Ich würde alle Bedingungen in einer if-Anweisung zusammenfassen, aber ich denke, Sie können nur `und` und nicht` oder` für if-Bedingungen tun. Ein Grund mehr, Powershell zu verwenden :) mrfreester vor 8 Jahren 0
Okay, um sicher zu gehen, dass ich das richtig verstehe. Ihr Code ersetzt meine IF-Anweisung, aber ich behalte die ersten 4 Zeilen, wie sie sind, richtig? Was mache ich dann mit dem "anderen" Teil? Fügen Sie es nach all meinen "IF" -Anweisungen mit einem "Echo" zur Protokolldatei hinzu? ps Ich bin offen dafür, dies mit PowerShell zu tun, aber ich weiß noch weniger über die Verwendung von PS. Es ist auf meiner Liste von Dingen, die ich bald lernen muss. WraythOsu vor 8 Jahren 0
Ich habe das gesamte Beispiel der Verwendung einer Variablen hinzugefügt, um zu sehen, ob etwas verschoben wurde. Sie verwenden diese anstelle einer else-Anweisung, da batch keine anderen ifs unterstützt mrfreester vor 8 Jahren 0
Es funktioniert!!! (stell dir den jungen Anakin in Eps 1 vor) :-) Letztes Bit ist das Löschen der alten Unterordner, nachdem wir die Dateien verschoben haben. füge ich also in jeder Anweisung rd / s / q %% G zwischen der `move'- und der` set`-Zeile hinzu? Meine einzige Sorge ist hier, dass ich keinen Ordner löschen möchte, der einen Dateityp enthält, den ich nicht im Skript berücksichtigt habe. Angenommen, ein Ordner erscheint als .msi anstelle von .exe. Ich möchte, dass der Ordner vorerst in Ruhe gelassen wird. Ich möchte also nur, dass ein Ordner gelöscht wird, wenn eine Datei ausgezogen wurde. WraythOsu vor 8 Jahren 0
Ich würde wahrscheinlich die Zeile `rd / q %% G` als letzten Block setzen, in den Sie in die Protokolldatei schreiben, da Sie dies nur dann tun sollten, wenn Sie in den vorherigen If-Blöcken etwas gelöscht haben. Ich würde wahrscheinlich die `/ s`-Option weglassen, da ich denke, dass das Verzeichnis gelöscht wird, auch wenn noch Dateien darin sind. Wenn Sie `/ s` weglassen, bin ich mir ziemlich sicher, dass es das tut, was Sie wollen, dh den Ordner nur dann löschen, wenn er leer ist. mrfreester vor 8 Jahren 0
Diese Antwort können Sie nach der gesamten for-Schleife ausführen, um alle leeren Ordner zu löschen. Sie müssen nur das angegebene Verzeichnis durch Ihre _parent-Variable ersetzen: http://superuser.com/a/39679/352083 mrfreester vor 8 Jahren 0
Danke, dass Sie bei mir dabei bleiben! Die Unterverzeichnisse sind also nicht leer, sie haben immer noch ein paar zusätzliche Dateien, die mir egal sind und die gelöscht werden sollen. Ich möchte also die `/ s` verwenden. Aber ich möchte nicht alles aus der _Parent runter löschen. Falls ein neuer Dateityp kommt, der nicht verschoben wird, möchte ich, dass der Ordner an seinem Platz bleibt, damit ich ihn auswerten kann. Ich möchte also nur die Ordner löschen, aus denen ich eine Datei verschoben habe. WraythOsu vor 8 Jahren 0
Okay, ich habe 'rd / s / q %% G' eingefügt und es hat gemacht, was ich wollte. Das einzige Problem war, dass ein Verzeichnis mit einem Leerzeichen nicht gelöscht wurde. Kann ich also einfach "" "" um das "%% G" setzen: `rd / s / q" %% G "`? Ich weiß, dass Zitate seltsame Dinge bewirken können, wenn sie nicht richtig gemacht werden. Alles was ich jetzt brauche, ist die korrekte Formatierung für diese Zeile, und diese wird beantwortet. woohoo! WraythOsu vor 8 Jahren 0
Aha. Es besteht die Möglichkeit, dass mit / s einige Ordner gelöscht werden, bevor Sie die Dateien verschieben, je nachdem, wie die Schleife durch Ordner durchläuft. Wenn Sie beispielsweise 'f1 / f2' mit Dateien darin haben und die Schleife zuerst durch 'f1' geht, können Sie beim Löschen dieses Ordners versehentlich alles in 'f2' entfernen. Möglicherweise möchten Sie einige Echo-Anweisungen einfügen, um die Reihenfolge zu sehen. Wenn die Schleife immer den obersten Ordner durchläuft, sollten Sie sich zuerst für glücklich halten und alles, was Sie tun müssen, ist, 'rd' in dieser letzten if-Anweisung zu verwenden. Wenn nicht so viel Glück, müssen Sie mehr Logik durcharbeiten. mrfreester vor 8 Jahren 0
Okay, ich verstehe, was Sie sagen, ich glaube nicht, dass ich Unter-Unterordner haben werde, also mache ich mir keine Sorgen. Deswegen brauchen Sie nur den Befehl `RD`, um Ordnernamen mit Leerzeichen zu behandeln, und wir sind fertig. WraythOsu vor 8 Jahren 0
Ja, das sollte alles sein, was Sie brauchen, setzen Sie einfach die Anführungszeichen um. Wenn das aus irgendeinem Grund nicht funktioniert, lass es mich wissen. mrfreester vor 8 Jahren 0
Das hat funktioniert, ich habe den Code in Ihrer Antwort bearbeitet und dies als beantwortet markiert. Vielen Dank für all Ihre Hilfe @mrfreester! WraythOsu vor 8 Jahren 0