Gerhard: Dateien umbenennen

Hi,
ich möchte alle Dateien *.shtml in meinen Ordnern in *.php umbenennen.
Ich habe zwar ein Programm, mit dem man Dateien in einem Ordner umbennen kann.
Bei meinen vielen Ordnern wäre dies aber sehr aufwendig.
Gibt es ein Programm, das dies in einem Ordner mit vielen Unterordnern macht?

  1. Lieber Gerhard,

    unter Linux wäre das auf der Kommando-Zeile mit rename sehr elegant lösbar. Aber wahrscheinlich bist Du unter Windows unterwegs, wo es auch verschiedene Möglichkeiten mit Boardmitteln gibt.

    Liebe Grüße

    Felix Riesterer

    1. Lieber Felix,
      mit den zitierten Bordmittel kann man nur die Dateien in einem ausgewählten Ordner umbenennen. Die Dateien in den Unterordnern werden dabei nicht berücksichtigt.
      Genau das aber möchte ich erreichen.

      1. Die Dateien in den Unterordnern werden dabei nicht berücksichtigt.

        Genau das aber möchte ich erreichen.

        Naja... Das kann man mit dem Pattern machen '.shtml' → '/*.shtml' - oder so:

        find ./ -type d -exec /home/meier/bin/my_renamer.sh "{}" \;
        

        Sucht ausgegehend vom aktuellen Ordner die Unterordner und übergibt diese an DEIN Skript /home/meier/bin/my_renamer.sh, welches die Dateien darin umbenennt.

        Schreib da Deinen Befehl rein und ein cd "$1" unter die Shebang. Lösche das Skript wenn Du fertig bist.

        Es gibt natürlich drölfzig weitere Lösungen mit langen Befehlszeilen.

    2. @@Felix Riesterer

      unter Linux wäre das auf der Kommando-Zeile mit rename sehr elegant lösbar. Aber wahrscheinlich bist Du unter Windows unterwegs, wo es auch

      … das Windows-Subsystem für Linux (WSL) gibt?

      🖖 Живіть довго і процвітайте

      --
      „Ukončete, prosím, výstup a nástup, dveře se zavírají.“
      1. Hallo Gunnar,

        kann man aus einem auf WSL installierten Linux auf das Windows-Filesystem hinausgreifen?

        Rolf

        --
        sumpsi - posui - obstruxi
        1. kann man aus einem auf WSL installierten Linux auf das Windows-Filesystem hinausgreifen?

          Das feine Manual sagt dazu...

          https://learn.microsoft.com/de-de/windows/wsl/filesystems

  2. Hallo Gerhard,

    ich möchte alle Dateien *.shtml in meinen Ordnern in *.php umbenennen.
    Ich habe zwar ein Programm, mit dem man Dateien in einem Ordner umbennen kann.

    Hm. Heißt es "Betriebssystem"? Wenn nicht: die diversen Dateimanager sind zwar nützlich, aber sie halten Dich auch davon ab, den Umgang mit deinem Betriebssystem zu erlernen.

    Windows Explorer ist ein besonders übles User-Verdummungs-Tool.

    Infos zu Linux hast Du bekommen. Unter Windows kann man das so machen:

    • Befehlszeile öffnen
    • In den Stammordner wechseln, in dem und unter dem die shtml Dateien liegen
    • Diesen Befehl ausführen - STOP, noch nicht. Erst fertig lesen.
    for /r %a in (*.shtml) do @move %a %~dpna.php
    

    for führt eine Aktion pro Datei aus, die auf das Muster in den Klammern passt, also auf *.shtml

    Diese Aktion steht hinter dem do.

    Die Option /r besagt: Hier und in allen Unterverzeichnissen (r wie rekursiv)

    %a ist der Name einer Variablen, die mit dem gefundenen Dateinamen zu befüllen ist und die nur während der ausgeführten Aktion einen Wert hat. So eine for-Variable darf nur aus einem Buchstaben bestehen und das % ist syntaktisch notwendig. Falls du den FOR-Befehl in einem CMD-Script verwenden willst, musst Du das % verdoppeln. Aber wirklich nur dann.

    Das Wort in ist syntaktisch nötig, aber ansonsten nur Dekorationsmaterial.

    Die ausgeführte Aktion ist der move Befehl. Das @ davor bedeutet nur: Schreib nicht für jede Datei in die Konsole, dass Du diesen Befehl ausführst (ein "ECHO OFF" für genau einen Befehl).

    move X Y kann Dateien in andere Ordner verschieben und sie auch am Platz umbenennen. Im Gegensatz zum RENAME Befehl kann ich auch C:\FOO als aktuellen Ordner haben und die Datei C:\FOO\BAR\HUGO\demo.shtml umbenennen. Rename macht (mir?) dabei Probleme, wenn ich in einem Netzwerkordner unterwegs bin.

    move C:\FOO\BAR\xyz.shtml C:\FOO\BAR\xyz.php würde also im Ordner C:\FOO\BAR die Datei xyz.shtml in xyz.php umbenennen.

    Als FOR-Aktion schrieb ich:

    @move %a %~dpna.php

    %a ist die Variable, die von FOR geliefert wird und für den gerade gefundenen Dateinamen steht. Mit dem ~ Zeichen werden Steuerzeichen eingeleitet, die nur einen Teil des Dateinamens liefern. d=Drive, p=Path, n=Name, x=Extension - danach kommt der Variablenname. %~dpna holt aus dem Dateinamen, der in %a steht, also Laufwerk, Pfad und Name heraus - alles außer der Extension, die ja shtml ist. Damit ist %~dpna.php der Name der shtml-Datei, mit einer auf php abgeänderten File-Extension. Und das wollen wir ja haben.

    Bevor Du das wirklich tust, führe in deinem Projekte-Ordner erst einmal diesen Befehl aus:

    for /r %a in (*.shtml) do @echo move %a %~dpna.php
    

    Durch den eingefügten ECHO wird der Move-Befehl erstmal nur angezeigt und nicht ausgeführt. Vergewissere Dich, dass die angezeigten move-Befehle Sinn ergeben. Wenn das zu schnell durchläuft, dann führe dies aus:

    for /r %a in (*.shtml) do @echo move %a %~dpna.php>>movelog.txt
    

    und schau Dir danach die Datei movelog.txt an. Falls Dein Projekteordner eine solche Datei schon enthält, denk Dir einen anderen Dateinamen aus.

    Erst wenn Du sicher bist, dass die move-Befehle sinnvoll sind, führe den Befehl ohne das echo aus.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,
      danke für Deine Erläuterungen.
      Da ich diese Befehle überhaupt nicht kenne, sagt mir die Fehlermeldung, die ich erhalten habe nichts. Ich könnte zwar die Klammer setzen, aber wo schließen?

      In Zeile:1 Zeichen:4
      + for /r %a in (*.shtml) do @echo move %a %~dpna.php>>movelog.txt
      +    ~
      Öffnende "(" fehlt nach dem Schlüsselwort "for".
          + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
          + FullyQualifiedErrorId : MissingOpenParenthesisAfterKeyword
      

      Gruß Gerhard

      1. Da ich diese Befehle überhaupt nicht kenne,

        Hm… Das sieht für mich so aus, als hättest Du die Syntax für die cmd.exe in der Powershell probiert. Das geht halt nicht mit allem, besonders nicht mit For.

        Powershell?

        https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell.core/about/about_for?view=powershell-7.3

        Terminal/CMD?

        https://ss64.com/nt/for.html

        Hint: Nimm für künftige Projekte entweder ein Betriebssystem oder die Powershell. Es sieht so aus, als wöllte M$ die cmd-Altlast loswerden

        1. Ich hatte es mit powershell versucht.
          Jetzt mit dem Dos-Fenster, da tat sich gar nichts
          und dann mit cmd, da kam aber die gleiche Fehlermeldung wie mit dem Powershell.

          1. Hallo Gerhard,

            wenn mit cmd die gleiche Meldung kam wie bei Powershell, dann lief die Powershell auch wieder.

            Wie Raketenwilli sagte: Microsoft will den Usern die Powershell aufnötigen, damit sie gar nichts mehr verstehen.

            Aber normalerweise sollte beim Aufruf von "cmd.exe" auch die Eingabeaufforderung starten und nicht die Powershell. Es gibt diverse andere Möglichkeiten zum Starten einer Eingabeaufforderung, und einige davon hat Microsoft zur Powershell verbogen. Da steht dann aber auch "Powershell" und nicht "Eingabeaufforderung".

            Mann mann mann, wieso muss MS immer alles kaputtmachen, was gut funktioniert?!

            Ich versuche mal, ein Powershellgebilde zusammenstricken, das den gleichen Zweck erfüllt – aber trotz aller Versuche, mit diesem Ding warmzuwerden, bin ich seit Jahren ein Powershelllegastheniker geblieben. Für jedes zweite Zeichen wühle ich in der Doku, um rauszukriegen, welche kryptische Option ich verwenden muss, damit das Ding tut, was ich will.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Wie Raketenwilli sagte: Microsoft will den Usern die Powershell aufnötigen, damit sie gar nichts mehr verstehen.

              Passt bis zum Komma. cmd hab ich lediglich „Altlast“ genannt und wähne mich dabei nahe an der Meinung der Verantwortlichen im Konzern.

          2. Hallo Gerhard,

            oookay.

            Angenommen, deine Projektdateien liegen in C:\Foo\Bar. Dann wäre es dieser Powershell-Befehl (alles auf einer Zeile):

            get-childitem C:\Foo\Bar\*.shtml -file -recurse | Rename-Item -NewName {[System.IO.Path]::GetFileNameWithoutExtension($_.Name) + ".php"}
            

            get-childitem ist das Cmdlet zum Auflisten eines Datencontainers. Bei Powershell kann das das Dateisystem sein, oder die Registry, oder ein paar andere Sachen. Hier ist es der Ordner C:\Foo\Bar und seine Unterordner, und darin die *.shtml Dateien.

            -file heißt: Finde nur Dateien. Einen Ordner test.shtml, falls es ihn gibt, wollen wir nicht umbenennen. Oder doch? Dann lass -file weg.

            -recurse ist das, wonach es aussieht: Wenn's eine Ordnerstruktur gibt, durchlaufe sie rekursiv

            | ist das Pipe-Zeichen: Die Ausgabe von Befehl 1 wird als Eingabe von Befehl 2 verwendet.

            Der Unterschied zwischen Powershell und vielen anderen Shells ist, dass es sich hierbei NICHT um Text handelt, sondern um eine Array, ein richtiges .net Array, von richtigen .net Objekten. In diesem Fall Objekte vom Typ System.IO.FileSystemInfo.

            Ein Powershell Cmdlet, das Pipe-Input verarbeiten kann, ist im Stande, ein solches Array zu durchlaufen. So auch das Cmdlet rename-item. Damit kann man Einträge in einem Speichersystem umbenennen, beispielsweise im Dateisystem.

            Das Rename-Item Cmdlet braucht natürlich den neuen Namen, und den übergibt man ihm über den -NewName Parameter. Und hier kann ich nicht einfach eine Zeichenkette angeben. "*.php" würde als neuer Name nicht verstanden. Ich muss anders auf den alten Namen Bezug nehmen. Und deshalb übergebe ich einen Script Block, also so ein Dings in geschweiften Klammern. Ein Script-Block ist eine Art primitiver Funktion, ohne Name und ohne explizite Angabe von Parametern. Das Rename-Item Cmdlet ruft ihn für jede Datei, die es umbenennen soll, neu auf. Innerhalb des Script-Blocks ist die Variable $_ verfügbar (alle Powershell-Variablen beginnen mit $), in der das Rename-Item Cmdlet das gerade verarbeitete FileSystemInfo-Objekt bereitstellt.

            Innerhalb des Scriptblocks benutze ich nun eine .net Klasse: System.IO.Path. Die eckigen Klammern sagen Powershell, dass dies eine .net Klasse ist. Diese Klasse hat eine statische Methode GetFileNameWithoutExtension, die einfach den letzten Punkt im Dateinamen sucht und alles, was davor steht, zurückgibt. Genau wie PHP verwendet Powershell den :: Operator, um auf statische Methoden einer Klasse zuzugreifen. Aber anders als PHP verwendet es den + Operator, um Strings zu verketten.

            Viele Beispiele im Netz schlagen vor, den Script-Block so zu schreiben: { $_.Name.replace(".shtml", ".php") }. Also einfach .shtml durch .php ersetzen. Das ist kürzer, sicher, aber kann in die Hose gehen, wenn eine Datei den String ".shtml" mitten im Namen trägt und nicht am Ende. GetFileNameWithoutExtension ist die sicherere Alternative.

            Tja. Nicht schön, nicht klein, aber sollte funktionieren.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo Rolf, es hat geklappt! Danke!

          3. Ich hatte es mit powershell versucht.

            Genau das hatte ich vermutet.

            Jetzt mit dem Dos-Fenster, da tat sich gar nichts

            Schauen wir mal nach …

            for /r %a in (*.shtml) do @echo move %a %~dpna.php>>movelog.txt
            

            Das „da tat sich gar nichts“ hat sich sehr wahrscheinlich im Erschaffen und Befüllen einer Datei mit dem Name movelog.txt „materilisiert“ und keine Ausgaben im Terminal hinterlassen. Das ist jedenfalls genau das, was ich bei dieser Befehlszeile erwarte.

            und dann mit cmd, da kam aber die gleiche Fehlermeldung wie mit dem Powershell.

            Eigentlich ist „Dos-Fenster“ und „cmd“ identisch. Es ist schwer etwas anderes dazu zu sagen als „Ich war nicht dabei. Vermutlich hast Du die Maus falsch geschubst.“


            P.S.

            Bin zurück aus dem Urlaub und hab das Badewetter aus dem Süden hochgeschubst.

            1. Hallo Raketenwilli,

              Eigentlich ist „Dos-Fenster“ und „cmd“ identisch.

              Ich bin mir nicht so sicher, was Windoof da treibt. Die Powershell hat Expansionsgelüste…

              Rolf

              --
              sumpsi - posui - obstruxi
            2. Hallo,

              Eigentlich ist „Dos-Fenster“ ...

              ... ein völlig falscher Ausdruck. Das hat mit DOS nichts zu tun. Es ist die Windows-Kommandozeile.

              Dass viele Kommandos immer noch mit denen aus DOS-Zeiten identisch sind, ist dabei unerheblich. Ganz abgesehen davon, dass DOS genaugenommen nur das Betriebssystem war und nicht die Shell.

              Einen schönen Tag noch
               Martin

              --
              Im Englischen hat eine Katze neun Leben. Im Deutschen vielleicht auch, aber nach Abzug der Steuern bleiben nur noch sieben übrig.