Dateiendungen umbenennen: zB alle *.txt in *.ini



  • Hallo,

    ich muss ein Programm schreiben welches Dateien umbenennen kann, zum einen ganz einfach wie der "mv" Befehl unter Linux aber auch mit der Möglichkeit alle Dateien mit der selben Dateiendung eine neue Endung zu geben.

    Also die Bedienung soll wie folgt sein:

    ./ren namealt.txt nameneu.txt
    Das hab ich hingekriegt, war nicht so schwer.

    Aber das Beispiel mit der Dateiendung:
    ./ren *.txt *.ini
    klappt nicht so einfach.

    Mein bisheriges Programm:

    #ifdef __unix__
        #include <unistd.h>
    #else
        #include <io.h>
    #endif 
    #include <time.h>
    #include <stdio.h>
    
    int main (int argc, char **argv)
    {
    	time_t t;
    	struct tm * ts;
    	t = time(NULL);
    	ts = localtime(&t);
    
    	FILE *log;
    
    	if(argc!=3){
    		printf("ERROR: Parameterfehler!\n");
    		log = fopen("./log.txt","a+");
    		fprintf(log, "%sERROR: Parameterfehler\n", asctime(ts));
    		fclose(log);
    		return 0;
    	}
    	else
    
    	if(access(argv[1], 00) == -1) {
    		printf("ERROR: %s nicht vorhanden!\n", argv[1]);
    		log = fopen("./log.txt","a+");
    		fprintf(log, "%sERROR: %s nicht vorhanden\n", asctime(ts), argv[1]);
    		fclose(log);
    		return 0;
    	}
    	else
    
    	if(access(argv[2], 00) != -1) {
    		printf("ERROR: %s bereits vorhanden!\n", argv[2]);
    		log = fopen("./log.txt","a+");
    		fprintf(log, "%sERROR: %s bereits vorhanden\n", asctime(ts), argv[2]);
    		fclose(log);
    		return 0;
    	}
    	else
    
    	printf("%s benennt jetzt %s in %s um! :-)\n", argv[0], argv[1], argv[2]);
    	rename(argv[1], argv[2]);
    
    	log = fopen("./log.txt","a+");
    	fprintf(log, "%s%s wurde in %s umbenannt\n",asctime(ts), argv[1], argv[2]);
    	fclose(log);
    	return 0; 
    
    }
    

    Habe da auch noch eine Logdatei eingbaut und ein paar if's bei falscher Bedienung. Grundlegen ist aber eben diser Teil für mein Vorhaben verantwortlich:

    rename(argv[1], argv[2]);
    

    Wenn ich da jetzt als Parameter nameneu.txt namealt.txt übergebe klappts auch. Aber wenn ich *.txt *.ini übergebe kommt die Meldung dass die *.txt Datei nicht gefunden wurde. Sie existiert ja auch nicht, das Sternchen ist nur Platzhalter (Wildcard).

    Jemand ne Idee ?
    Und nochwas; Bei meiner Logdatei kommt immer automatisch ein Absatz nach dem Datum, sieht im Quellcode hier deswegen auch etwas seltsam aus:

    fprintf(log, "%s%s wurde in %s umbenannt\n",asctime(ts), argv[1], argv[2]);
    

    Aber nach dem ersten %s welches ja asctime(ts) entpricht kommt automatisch eine neue Zeile. Notfalls kann ich damit leben da die log Datei eh nur otional ist aber mich störts ein bisschen 😉 (Wollte nämlich pro Ereignis nur eine Zeile und nicht eine für Datum und eine für Ereignis.)

    Und allgmein noch: Ich bin totaler noob was das ganze Programmien angeht und bin mir durchaus bewusst dass mein Programm noch "sauberer" sein könnte. Ich hab erstmal einfach drauflosprobiert und war schon froh dass es jetzt zumindest teilweise funktioniert 🙄



  • Du musst da aufpassen.

    Unter *ix macht normalerweise die Shell die Wildcardersetzung.
    Du würdest bei *.txt ein paar mehr Argumente in argv bekommen.

    Unter Windows passiert das nicht. Da musst du dann Funktionen von Windows benutzen.



  • Also eine Möglichkeit wäre (wenn auch keine schöne)

    MoveFile("C:\\Text.txt","C:\\MeinText.html")
    


  • DirkB schrieb:

    Unter *ix macht normalerweise die Shell die Wildcardersetzung.
    Du würdest bei *.txt ein paar mehr Argumente in argv bekommen.

    Unter Windows passiert das nicht. Da musst du dann Funktionen von Windows benutzen.

    Ja ich habe schon gemerkt dass unter Linux ich zB

    ./ren nameal*.txt nameneu.txt
    

    eingebe kann und es einwandfrei funktioniert. Das Terminal hat dieses Feature ja eingebaut und übernimmt diesen Part dann. Unter Windows funktiniert das aber nicht.
    In erster Linie muss es auch nur unter Linux funktioniueren.

    Was meinst du aber damit das ich mehr argumente in argv bekomme?? Verstehe grade nicht ob Du meinst ich muss mehr eingeben muss oder mein programm erhält bei *.txt mehr(=zviel) als parameter ?

    TocToc schrieb:

    Also eine Möglichkeit wäre (wenn auch keine schöne)

    MoveFile("C:\\Text.txt","C:\\MeinText.html")
    

    Damit ändere ich doch nur den Namen von Text.txt in meintext.txt oder? Den Befehl MoveFile unter C kenn ich jetzt nicht aber wenn wie im Linuxshell mv ist wäre das ja einfaches umbennenen. Das klappt ja bereits. Aber ich möchte zb zehn *.txt Dateien im verzeichnis alle auf einen schlag in *.ini umbennenen.
    Habe den Befehl "MoveFile" eben ausprobiert. Egal ob unter Win oder Linux, es treten Kompilierungsehler auf weil scheinbar der Befehl "MoveFile" nicht existiert. Muss ich evtl eine weitere Bibliothek mit einbinden?



  • Alfex schrieb:

    Was meinst du aber damit das ich mehr argumente in argv bekomme?? Verstehe grade nicht ob Du meinst ich muss mehr eingeben muss oder mein programm erhält bei *.txt mehr(=zviel) als parameter ?

    Lass dir am Anfang vom Programm doch mal den Wert von argc und alle Elemente von argv ausgeben.



  • DirkB schrieb:

    Alfex schrieb:

    Was meinst du aber damit das ich mehr argumente in argv bekomme?? Verstehe grade nicht ob Du meinst ich muss mehr eingeben muss oder mein programm erhält bei *.txt mehr(=zviel) als parameter ?

    Lass dir am Anfang vom Programm doch mal den Wert von argc und alle Elemente von argv ausgeben.

    Oh ja, ich bin doof 🙄

    habe mir den Fehler ja selber eingebaut.

    Hier mein Code:

    #ifdef __unix__
        #include <unistd.h>
    #else
        #include <io.h>
    #endif 
    #include <stdio.h>
    
    int main (int argc, char **argv)
    {
    
    	printf("%s\n%s\n%s\n%s\n%s\n", 
    	argv[1],
    	argv[2],
    	argv[3],
    	argv[4],
    	argv[5]);
    
    	printf("Anzahl Parameter: %i\n", argc);
    
    	if(argc!=3){
    		printf("ERROR: Parameterfehler!\n");
    		return 0;
    	}
    	else
    
    	if(access(argv[1], 00) == -1) {
    		printf("ERROR: %s nicht vorhanden!\n", argv[1]);
    		return 0;
    	}
    	else
    
    	if(access(argv[2], 00) != -1) {
    		printf("ERROR: %s bereits vorhanden!\n", argv[2]);
    		return 0;
    	}
    	else
    
    	printf("%s benennt jetzt %s in %s um! :-)\n", argv[0], argv[1], argv[2]);
    	rename(argv[1], argv[2]);
    
    	return 0; 
    
    }
    

    (Der übersicht halber hab ich die logdatei weggelassen)

    Und hier die Ausgabe:

    alex@debian:~/Schreibtisch/cprog$ gcc ver.c -o ver
    alex@debian:~/Schreibtisch/cprog$ ./ver *.txt *.ini
    32.txt
    3.txt
    44.txt
    555.txt
    log.txt
    Anzahl Parameter: 8
    ERROR: Parameterfehler!
    alex@debian:~/Schreibtisch/cprog$
    

    Frage:
    Ich hab ja jetzt nur die ersten 5 Parameter (bzw den allerersten also den 0ten hab ich weggelassen) ausgeben lassen. Gibts einen Weg wirklich alle auszugeben?
    Also egal ob 5 der 500 dass alle ausgegeben werden?



  • Alfex schrieb:

    Gibts einen Weg wirklich alle auszugeben?
    Also egal ob 5 der 500 dass alle ausgegeben werden?

    Klar. Schleife die von 1 ... (argc-1) läuft.



  • hustbaer schrieb:

    Alfex schrieb:

    Gibts einen Weg wirklich alle auszugeben?
    Also egal ob 5 der 500 dass alle ausgegeben werden?

    Klar. Schleife die von 1 ... (argc-1) läuft.

    Danke für den Tipp! Einfacher als gedacht, aber mussste erstmal etwas tüfteln. 🙂

    int main (int argc, char **argv)
    {
      printf("Anzahl Parameter: %i\n", argc);
      int i=0;
     while (i<=argc-1){
       printf("Parameter Nummer %i: %s\n", i, argv[i]);
       i++;
     }
    
    }
    

    Ergebnis:

    alex@debian:~/Schreibtisch/cprog$ gcc schleife.c -o schleife
    alex@debian:~/Schreibtisch/cprog$ ./schleife 345.txt 44.log s hallo 123 46 ende
    Anzahl Parameter: 8
    Parameter Nummer 0: ./schleife
    Parameter Nummer 1: 345.txt
    Parameter Nummer 2: 44.log
    Parameter Nummer 3: s
    Parameter Nummer 4: hallo
    Parameter Nummer 5: 123
    Parameter Nummer 6: 46
    Parameter Nummer 7: ende
    alex@debian:~/Schreibtisch/cprog$
    

    Oder jetzt mit Wildcard:

    alex@debian:~/Schreibtisch/cprog$ ./schleife *.txt
    Anzahl Parameter: 7
    Parameter Nummer 0: ./schleife
    Parameter Nummer 1: 32.txt
    Parameter Nummer 2: 3.txt
    Parameter Nummer 3: 44.txt
    Parameter Nummer 4: 555.txt
    Parameter Nummer 5: log.txt
    Parameter Nummer 6: reogl.txt
    alex@debian:~/Schreibtisch/cprog$
    

    So und jetz tüftel ich daran wie es weitergeht mit dem Umbenennen... 🙄



  • Alfex schrieb:

    while (i<=argc-1){
    

    In C schreibt man gewöhnlich < grenze
    Also

    while (i<argc)
    

    Das versteht jeder C-Programmierer sofort ohne Nachdenken.



  • Alfex schrieb:

    ich muss ein Programm schreiben welches Dateien umbenennen kann, zum einen ganz einfach wie der "mv" Befehl unter Linux aber auch mit der Möglichkeit alle Dateien mit der selben Dateiendung eine neue Endung zu geben.

    Alfex schrieb:

    In erster Linie muss es auch nur unter Linux funktioniueren.

    Hast Du kein rename(1) ?



  • DirkB schrieb:

    ]In C schreibt man gewöhnlich < grenze

    Danke für den Hinweis!

    Furble Wurble schrieb:

    Hast Du kein rename(1) ?

    Ich kann dir nicht ganz folgen? 😕 Was meinst du damit?


  • Mod

    Alfex schrieb:

    Furble Wurble schrieb:

    Hast Du kein rename(1) ?

    Ich kann dir nicht ganz folgen? 😕 Was meinst du damit?

    Die Zahlen bei Manpages:
    1. Executables
    2. Systemfunktionen
    3. Bibliotheksfunktionen
    ...

    Es ist ein bisschen merkwürdig, ein Programm schreiben zu wollen, das nicht mehr ist als ein Frontend für die System- bzw. Bibliotheksfunktion rename (also rename(2) bzw. rename(3)), wenn es bereits auf jedem Linuxsystem ein Programm namens rename geben sollte (also rename(1)), welches genau solch ein Frontend darstellt.

    man: rename(2): Von dir benutzt; Linux-Kernelfunktion
    man: rename(3): Das gleiche, nach einem etwas allgemeineren Standard
    man: rename(1): Ein Programm, das es auf jedem Linuxsystem gibt und das genau das gleiche tut wie dein Programm, bloß viel besser. Rate mal, was das intern wohl benutzt.



  • Alfex schrieb:

    Furble Wurble schrieb:

    Hast Du kein rename(1) ?

    Ich kann dir nicht ganz folgen? 😕 Was meinst du damit?

    man rename(1)
    

    kannst du in der Konsole/Terminal oder bei Google eingeben.

    Falls du die man-pages nicht kennst: https://de.wikipedia.org/wiki/Manpage



  • Der praktische Hintergrund ist leider nicht vorhanden, das stimmt ... 🙄
    Ich verstehe auch dass ihr mir daher andere Lösungswege nahelegt, ich soll zu Übungszwecken aber eben den Befehl "nachprogrammieren"


Anmelden zum Antworten