Skript mit Dateiname als Variable



  • Hallo liebe Community,

    nach verzweifelter Suche im www. bin ich nun hier bei euch gelandet, in der Hoffnung, dass mir vlt. hier geholfen werden kann. Ich besitze grundlegende Kenntnisse was Batch-Dateien angeht, mein Problem ist dafür glaub ich allerdings zu Komplex, wodurch ich mich wohl mit C beschäftigen muss. Folgende Problemstellung: Ich besitze ca. 4000-5000 Text-Dateien (abgespeichert als .nc) und in jeder dieser Textdateien gehören Änderungen vorgenommen (was manuell ewig dauern würde) deshalb will ich mir dafür ein Skript schreiben. Folgendes soll passieren: Die erste Zeile soll egal wie sie heißt in %PM geändert werden, in der 2. Zeile soll der Dateiname in Klammern an die Zeile angehängt werden.

    Beispiel: Dateiname ist hier 1234567801.nc

    Die Datei sieht vorher so aus:
    %PM666000
    N666000
    N1 X20 Y40
    N2 X50 Z120...

    und sollte danach so aussehen:
    %PM
    N666000 (1234567801)
    N1 X20 Y40
    N2 X50 Z120...

    Ich hab mich schon durch einige Foren gewühlt, bin aber noch auf keine Lösung gestoßen wie sich das halbwegs realisieren lässt, wenn man nicht gerade eine Profi auf dem Gebiet ist. Mit welchen Befehlen lässt sich dieses Problem am einfachsten realisieren?

    Vielen Dank schon mal für etwaige Hilfe

    Polarnacht



  • Naja da du hier ja in c++ gelandet bist wirst du wohl auch einen c++ Ansatz wollen?!

    Siehe hier:
    http://www.c-plusplus.net/forum/252481?highlight=dateioperationen
    oder auch hier:
    http://www.c-plusplus.net/forum/39351

    Referenz:
    http://www.cplusplus.com/reference/iostream/fstream/

    Wenn du einen Script-Ansatz suchst dann wäre evtl. SED was für dich
    http://de.wikipedia.org/wiki/Sed_%28Unix%29

    Hoffe konnte dir helfen,

    viel Erfolg

    Wolfgang



  • Ich besitze ca. 4000-5000 Text-Dateien (abgespeichert als .nc) und in jeder dieser Textdateien gehören Änderungen vorgenommen (was manuell ewig dauern würde)

    Das nen typischer anwendungsfall für eine Programmiersprache allgemein.

    wodurch ich mich wohl mit C beschäftigen muss

    Naja, das waere wohl eher mit Kanonen auf Spatzen geschossen ...

    also
    1. Ja du solltest Dich mit einer Programmiersprache / Scriptsprache auseinandersetzen.
    2. es muss nicht c/c++ sein, andere Sprachen sind einfacher zu erlernen und grad bei modifizieren von Textdateien aehnlich performant.
    3. wenn dein system erweiterst und eine scriptsprache verwendest, kannst die fast verwenden wie nen shellsript (shebang). Fühlt sich dann fasst an wie nen batchfile. Nix ist schoener wie alte Gewohnheiten pflegen 🙂

    Textdateien manipulieren kann fast jede Sprache, deshalb iss schwer was zu empfehlen.
    Kandidaten mit existierenden Interpreter für windows/Linux waeren z.b.:
    Python, Perl, Ruby, lua, java/script, Basic in verschiedenen Dialekten, TCL .... u.v.m.

    Kommts Dir aber aufs Lernen einer ziemlich machinennahen Sprache an, und ist Performance im Detail nen wichtiges argument, dann bist bei c/c++ vielleicht doch richtig.

    Kommts Dir aber nur aufs Loesen deines obigen Problems an -> ist der Aufwand mit ner scriptsprache um Faktor X geringer.
    Ich kann c/c++, aber so wie dein Problem beschreibst, wuerd ich das auch eher in python loesen 🙂

    Ciao ....



  • Vielen Dank erstmal für die flotte Antwort,
    ich glaube das mit dem Zeilen ändern bekomme ich hin, ich weiss nur nicht so recht, wie ich das mit dem Dateinamen umsetzen vernünftig hinbekomme, da ich leider nichts finde, womit ich den Dateinamen auslesen und zb. als Variable setzen kann, damit ich ihn in Klammern in der 2. anfügen kann.

    char i;
    i = [Funktion zum auslesen von Dateinamen]??



  • Polarnacht schrieb:

    ich glaube das mit dem Zeilen ändern bekomme ich hin, ich weiss nur nicht so recht, wie ich das mit dem Dateinamen umsetzen vernünftig hinbekomme, da ich leider nichts finde, womit ich den Dateinamen auslesen und zb. als Variable setzen kann, damit ich ihn in Klammern in der 2. anfügen kann.

    Du hast doch den Dateinamen irgendwo abgespeichert, wie hast du sonst die Datei öffnen können?
    (Ich hoffe jetzt mal, dass du nicht für jede Datei dein Programm änderst und den Namen manuell einträgst)



  • pumuckl schrieb:

    (Ich hoffe jetzt mal, dass du nicht für jede Datei dein Programm änderst und den Namen manuell einträgst)

    genau das will ich eben umgehen, doch ich weiss mir einfach nicht recht zu helfen. Die Sprache ist mir prinzipiell eig. egal, da es ein einmaliges Problem ist, dass in dieser Form nicht wieder auftreten wird. Ich hab prinzipiell nicht allzuviel mit Programmiersprachen zu tun (schreibe höchstens ab und an mal ne einfachere Batch-Datei). Mein Problem ist nur, dass ich mit .NC Programmen, also Steuerprogrammen für CAD-Maschinen arbeite und meine neue Maschine eine gewisse Struktur innerhalb der .txt Dateien vorraussetzt, ich aber meine alten schon geschriebenen Programme weiterhin verwenden möchte, da es ein riesen Aufwand wäre alle 5000 Programme für die neue Maschine nochmal zu schreiben (da wäre ich selbst dann noch schneller, wenn ich alles per Hand umschreiben würde) 😉
    Ich habe C++ deswegen ausgewählt, weil sie mir noch am geläufigsten ist (im Gegensatz zu Python)



  • Nach allem was ich jetzt gelesen habe ist ein batch-Script so ziemlich genau das richtige für dein Problem. Wenn du wie ich vermute auf Windows unterwegs bist. Alternativ eben Linux-Shell Scripte. Die genaue Batch-Syntax kenne ich nicht, ich schreib mal ganz banalen Pseudocode hin (geht bestimmt besser):

    for $DATEINAME in $(dir *.nc)
    do
       open "tmp.nc"
       open $DATEINAME
       copy erste zwei Zeilen von $DATEINAME nach "tmp.nc"
       print $DATEINAME in zweite Zeile von "tmp.nc" 
       copy restliche Zeilen von $DATEINAME nach "tmp.nc"
       close $DATEINAME
       close "tmp.nc"
       del $DATEINAME
       rename "tmp.nc" $DATEINAME
    done
    

    Was ich damit Zeigen will: so ziemlich jede Script/Shellsprache bietet Möglichkeiten für Schleifen über alle Dateien eines Suchergebnisses und speichert den grade aktuellen Dateinamen in einer Variablen. Mach dich mal über die batch-Syntax schlau, da wirds sowas sicher auch geben.



  • Dieser Thread wurde von Moderator/in pumuckl aus dem Forum C++ (auch C++0x) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Bin auch nur Anfänger in Bezug auf C++ aber wenn du schon hier geschrieben hast möchte ich dir auch in der entsprechenden Richtung helfen:

    #include <dirent.h>
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    using namespace std;
    
    void debug(string filename, string action, string message="--")
    {
    	cout << "[" << action << "]\t" << filename << "\t- " << message << endl;
    	return;
    }
    int main()
    {
    	DIR *hdir;
    	struct dirent *entry;
    	string cfname, nfname, buffer;
    	int cfnsize;
    	ifstream fin;
    	ofstream fout;
    
    	hdir = opendir(".");
    	do
    	{
    		entry = readdir(hdir);
    		if (entry)
    		{
    			cfname = entry->d_name;
    			cfnsize = cfname.size();
    			if (cfnsize > 3 && cfname.compare(cfnsize-3,3,".nc") == 0)
    			{
    				std::vector<std::string> fcontent;
    				fin.open(cfname.c_str(), ios::in);
    				if (fin)
    				{
    					fin.seekg(0);
    					while (!fin.eof())
    					{
    						getline(fin,buffer);
    						fcontent.push_back(buffer);
    					}
    					fin.close();
    					if (fcontent.size() > 3)
    					{
    						nfname = cfname.substr(0,cfnsize-3) + ".new";
    						fcontent[0] = "%PM" + fcontent[0].substr(fcontent[0].size()-1,1);
    						fcontent[1] =
    							fcontent[1].substr(0,fcontent[1].size()-1) +
    							" (" + cfname + ")" +
    							fcontent[1].substr(fcontent[1].size()-1,1);
    						fout.open(nfname.c_str(), ios::out | ios::trunc);
    						if (fout)
    						{
    							for (int i = 0; i < fcontent.size(); i++)
    							{
    								fout << fcontent[i];
    							}
    							fout.close();
    						}
    						debug(nfname, "created");
    					} else
    					{
    						debug(cfname,"  ignored",("it has less than 3 lines in it"));
                        }
    				}
    			} else
    			{
    				debug(cfname," ignored");
    			}
            }
        } while (entry);
        closedir(hdir);
    }
    

    So dürfte es auf Linux wohl hinhauen...

    Gruß, Wolfgang



  • In Ruby kann man es so machen (geht bestimmt besser, aber funktioniert):

    files = Dir.entries('.').reject { |name| File.directory?(name) or File.extname(name) != '.nc' }
    for file in files
    	lines = IO.readlines file
    	File.open(file, 'w') do |out|
    		out.write "%PM\n"
    		out.write lines[1].chomp
    		out.write " (#{File.basename(file, '.nc')})\n"
    		for line in lines[2..-1]
    			out.write line
    		end
    	end
    end
    


  • warum die Technik von heute benutzen, wenn man auch die von morgen haben kann ? 😕

    Smalltalk:

    files := FileDirectory default 
    	fileNamesMatching: '*.nc'.
    files do: [ :oldName |
    	| lines name newFile newName |
    	lines := (StandardFileStream 
    		oldFileNamed: oldName) 
    			readOnly contents lines.
    	name := FileDirectory 
    		baseNameFor: oldName.
    	newName := name, '.nc.new'.
    	newFile := StandardFileStream 
    		forceNewFileNamed: newName.
    	newFile 
    		nextPutAll: '%PM'; 
    		crlf.
    	lines at: 2 
    		put: (lines at: 2), '  (' asString, name, ')' asString.
    	lines allButFirstDo: [ :line |
    		newFile 
    			nextPutAll: line; 
    			crlf ] ].
    


  • !rr!rr_. schrieb:

    warum die Technik von heute benutzen, wenn man auch die von morgen haben kann ? 😕

    Smalltalk:

    LOL. Smalltalk ist Anfang der 70er entstanden, war nie praktisch relevant und wird es auch nie sein.



  • Smalltalk ist Anfang der 70er entstanden, war nie praktisch relevant und wird es auch nie sein.

    Laß mich das mit zwei Einzeilern beantworten:

    smalltalk (1972-1980):

    1 to: 10 do: [ :n | 
        Transcript show: n asString, '.' ].
    

    ruby (1993-):

    1.upto(10) { | n | STDOUT.write print n, "." }
    

    😃

    Smalltalk gehört gemeinsam mit Sprachen wie LISP, Algol, APL und Prolog zu den einflußreichsten Programmiersprachen überhaupt.

    (außerdem fällt mir gerade auf, daß in der 5. zeile von unten die beiden #asString überflüssig sind.)



  • Ich denke nicht, dass dies Gegenstand dieses Threads ist.

    @ Polarnacht, hoffe dir konnte mit den vorgeschlagenen Lösungen geholfen werden (ist nicht der Standard dass du hier fertige Codes bekommst... also schön Danke sagen :D)

    Welche der Lösungen du verwendest bleibt wohl dir überlassen - wichtig ist dass du verstehst was du da ausführst.

    Viel Glück jedenfalls!



  • !rr!rr_. schrieb:

    Smalltalk gehört gemeinsam mit Sprachen wie LISP, Algol, APL und Prolog zu den einflußreichsten Programmiersprachen überhaupt.

    Was nicht heisst dass es jemals praktisch relevant gewesen sein muss.



  • Du willst uns auf den Arm nehmen, oder? 😃

    Smalltalk ist ebenso relevant wie die 5 Prinzipien der OOP ("alles ist ein Objekt" usw) - Smalltalk ist nämlich eine Modell-Implementation dieser Prinzipien.

    Und davon gibt es nicht viele - mir fällt im Moment nur noch Self ein, der Prototypen-basierte "Neffe" von Smalltalk. Der erfüllt aber Prinzip #2 ("Jedes Objekt ist Instanz einer Klasse") nicht.



  • ... was im Falle von Self selbstverständlich kein Mangel, sondern ein Feature ist: Prototypenbasierte statt Klassenbasierte OOP.



  • Vermutlich definierst du "praktisch Relevant" anders als ich.

    Wenn ich schreibe (sinngemäss) "hat viel Einfluss gehabt" heisst das nicht "war praktisch relevant", dann meine ich mit dem "praktisch relevant" Teil: wurde es ausserhalb der akademischen Welt "in der Praxis" von vielen Leuten eingesetzt?

    Was konkret Smalltalk angeht:

    Möglich dass Smalltalk viel in der Industrie eingesetzt wurde, aber ich bezweifle es. Zumindest wenn wir "viel" als "annähernd so viel wie C/BCPL/..." definieren. Mag sein dass ich mich da täusche, aber egal, darum geht es (mir) nicht wirklich.

    D.h. man kann (nach meiner Definition von "praktisch relevant") auch nicht behapten dass irgendwas "praktisch relevant" (gewesen) sein muss, nur weil es viele Dinge die heute durchaus "praktisch relevant" sind beeinflusst hat.

    Das wollte ich damit sagen. Mehr nicht 🙂

    ps: "alles ist ein Objekt" ist ein "Prinzip der OOP" das ich nicht anerkenne.



  • sollte man diese Diskussion nicht in einen getrennten Thread auslagern? das gehört wirklich nicht mehr zur eigentlichen Frage.

    hustbaer schrieb:

    ps: "alles ist ein Objekt" ist ein "Prinzip der OOP" das ich nicht anerkenne.

    Object-Message-Passing ist eine zentrale Eigenschaft von OOP - da sind wir wohl einig. In einem System, in dem nicht alles Objekt ist, gibt es demnach Funktionalität, die nicht durch Object-Message-Passing erreichbar ist.

    Außerdem ist "alles ist ein Objekt" eines der 5, 6 oder 17 (je nach Quelle) Prinzipien, nach denen DIE Modell-Implementierung von OO (Smalltalk) gebaut ist.

    hustbaer schrieb:

    Wenn ich schreibe (sinngemäss) "hat viel Einfluss gehabt" heisst das nicht "war praktisch relevant",

    Ideen und Prinzipien, die von aller Welt benutzt werden, sind doch praktisch relevant?



  • !rr!rr_. schrieb:

    Object-Message-Passing ist eine zentrale Eigenschaft von OOP - da sind wir wohl einig. In einem System, in dem nicht alles Objekt ist, gibt es demnach Funktionalität, die nicht durch Object-Message-Passing erreichbar ist.

    Funktionsaufrufe sind wichtig bei jeglicher Art der Programmierung.
    Sie als "Object-Message-Passing" zu bezeichnen ändert daran nichts, und macht es auch nicht neu oder OOP-spezifisch.

    Falls du damit Dynamic Dispatching oder "Multiple Dispatch" meinen solltest: nö, ist für OOP nicht nötig.


Anmelden zum Antworten