[Tcl / Shell] Ändern einer Datei per vi - Änderungsdatum einer Datei erfassen

Dieses Thema im Forum "Shell-Skripte" wurde erstellt von lePasteur, 11.03.2010.

  1. #1 lePasteur, 11.03.2010
    Zuletzt bearbeitet: 11.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Hallo liebe Leute,

    ich habe zwei Probleme, die ich bisher nicht lösen kann, ich hoffe, ihr könnt mir hier weiterhelfen.

    Mein erstes Problem:

    Ich schreibe gerade ein tcl-Skript, in dem eine Datei verändert werden soll.
    Das heisst, ich versuche über den vi diese Datei zu öffnen, eine Zeile zu löschen und zu beenden. Also rufe ich folgenden Befehl im Skript auf:
    Code:
    exec vi "dateiname" << EOF
    /sucheWort
    D
    ZZ
    EOF
    Dies funktioniert aber so nicht, es wird eine sehr lange Fehlermeldung angezeigt, u.a. steht dort drin "Found a swap file by the name "~/dateiname.swp" und "Swap file already exists".

    Wenn ich iesen Code in meiner shell eingebe (ich benutze SuSE 9.x) kommt die Meldung: "Vim: Warning: Input is not from a terminal" und in der nöchsten Zeile steht in der Eingabe "0;115;0c"

    Mein Ziel ist es, im Tcl Skript eine Zeile in einer Textdatei zu suchen, löschen und nachträglich zu ersetzen (hab ich oben bewusst noch nicht gemacht, da ich es bisher alternativ mit cat gelöst habe, was aber auch nicht besonders nützlich ist, da der neue Text an die Stelle des alten sollte).
    Wisst ihr, wie das geht? Ich arbeite noch nicht lange mit UNIX, deshalb weiss ich auch nicht, was ihr noch für Angaben braucht.



    Mein zweites Problem:

    In jenem Tcl Skript soll ich das letzte Änderungsdatum einer bestimmten Datei finden. Habe bisher mit "find -mtime datei" das versucht, aber bei zwei gleichen Dateien, die am gleichen Datum geändert wurden, kommen verschiedene Ergebenisse.
    Gibt es einen Tcl oder shell Befehl, mit dem ich direkt das Datum als String bekomme, um zu schauen, welche Datei älter ist?

    Ich hoffe, ihr versteht mein Problem und könnt mir helfen.
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. #2 floyd62, 11.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Hi,

    ad 1) probiers mal an Stelle von "vi" mit "sed" und einem Konstrukt wie
    Code:
    sed -e 's/sucheWort.*/ersetzeRestvonZeile/' dateiname >dateiname.$$
    mv dateiname.$$ dateiname
    
    Gibt zig andere Möglichkeiten (ed, inline edit mit Perl, ...), aber "vi" zu skripten, ist meist nicht die einfachste Lösung ;-)

    ad 2) schon mal das file-Kommando in Tcl, speziell die Operation mtime angeschaut? Sollte doch genau das gewünschte liefern ...

    Gruesse,
    A.
     
  4. #3 lePasteur, 11.03.2010
    Zuletzt bearbeitet: 11.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    1) werd ich gleich mal schauen ob das klappt.

    2) Ja, das habe ich bisher benutzt, nur ich bekomme unterschiedliche Strings bei zwei verschiedenen Dateien, die aber gleichzeitig erstellt wurden, das macht mich stutzig.
    Habe gerade "test -nt gefunden", werde das auch gleich mal probieren, wollte nur schnell antworten.

    Edit:

    zu 2)
    also hab es mal im Skript beispielsweise versucht mit
    Code:
    set t [exec test datei1 -nt datei2]
    puts $t
    
    was aber die Meldung
    "child process exited abnormally"
    brachte.


    zu 1)
    Da ist mir die Syntax nicht ganz klar. Welche Anführungszeichen muss ich benutzen? bei ' kommt die meldung, dass der command name '' unbekannt ist. Bei " " kommt "Error:sed: -e expression #1, char 26: unknown option to 's' "
     
  5. #4 floyd62, 11.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Hi,

    ad 1) bei mir läuft das mit single quotes wie im Beispiel oben; direkt nochmal mit copy & paste getestet. Evtl. kannst du ja mal das genaue Kommando hier reinkopieren, das bei dir zu der Fehlermeldung geführt hat?

    ad 2) noch ein bisschen mit Tcl rumgespielt (ist lange her :) ) ... bei mir funktioniert das mit 'file mtime ...' problemlos:
    Code:
    #!/usr/bin/tclsh
    
    
    set t1 [file mtime TEST1]
    puts "TEST1: $t1"
    
    set t2 [file mtime TEST2]
    puts "TEST2: $t2"
    
    if { $t1 < $t2 } {
            puts "\nTEST2 is NEWER"
    } else {
            puts "\nTEST1 is NEWER"
    }
    
    Dein "test ... -nt" liefert dir nicht den Namen (oder das Modifikationsdatum) der neueren Datei zurück, sondern einen Exit-Status 0, wenn die zuerst genannte neuer ist als die zweite, sonst 1. "child process terminated abnormally" heisst also m.E. nur, dass deine zweite Datei die neuere ist.

    Gruss, A.
     
  6. #5 lePasteur, 11.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Also es kommt mit copy und paste folgende Fehlerneldung:

    Code:
    sed: -e expression #1, char 1: unknown command: `''
    sed: -e expression #1, char 1: unknown command: `''
        while executing
    "exec sed -e 's/$nkey.*/$nkey [.cfgwin.$path get]/' $CFG(PATHCFG) >$CFG(PATHCFG).$$"
        (procedure "sav" line 23)
        invoked from within
    "sav INST_DICT destentry  "
        invoked from within
    ".cfgwin.destsave invoke"
        ("uplevel" body line 1)
        invoked from within
    "uplevel #0 [list $w invoke]"
        (procedure "tk::ButtonUp" line 22)
        invoked from within
    "tk::ButtonUp .cfgwin.destsave"
        (command bound to event)
    Muss ein exec davor oder nicht?

    zu 2) Bei anderen Dateien klappt es, jedenfalls die, die ich getestet habe. Nur da war jetzt ein kleiner Fehler drinne, der mich stutzig macht.
     
  7. #6 floyd62, 11.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Braucht auf jeden Fall ein exec davor; und innerhalb des tcl-Skripts musst du doch double quotes verwenden (ich hatte das nur auf der Kommandozeile getestet).

    A.
     
  8. #7 lePasteur, 11.03.2010
    Zuletzt bearbeitet: 11.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Wenn ich das sed .... $$ in """ setze, kommt die Fehlermeldung: Couldn't execute "sed -e ...." no such file or directory.

    In der Shell funktionier das Kommando einwandfrei, aber im Tclskript kommt, wenn ich das ganze hinter exec schreibe, der Fehler:

    Error:sed: -e expression #1, char 26: unknown option to 's'.
     
  9. #8 floyd62, 11.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    ... mal nur um den "Substitute"-Befehl:
    Code:
    exec sed -e "s/$nkey.*/$nkey [.cfgwin.$path get]/" ...
    
     
  10. #9 lePasteur, 11.03.2010
    Zuletzt bearbeitet: 11.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Bei " " kommt der gleiche Fehler, und bei ' ' kommt der Fehler mit ' ' statt 's' :(
    Und ganz ohne Leerzeichen klappt auch nich.
     
  11. #10 floyd62, 11.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Also, wenn ich das in 'ne tclsh paste, bekomme ich nur eine Meldung wie
    Code:
    % exec sed -e "s/$nkey.*/$nkey [.cfgwin.$path get]/" <DATA
    can't read "nkey": no such variable
    %
    
    und das Bsp. von vorhin mit Dummy-Daten und double-quotes ist bei mir so gelaufen.

    Könnte mir noch vorstellen, dass die "square brackets" innerhalb des substitute-Befehls noch Probleme machen, weil die ja auch noch von Tcl ausgewertet werden; würde da aber eigentlich 'ne andere Fehlermeldung erwarten ...

    Kannst du mal ein paar Zeilen Code rüberschieben, die möglichst standalone lauffähig sind, um das Problem zu reproduzieren? Oder hat sich die Geschichte inzwischen sowieso erledigt?
     
  12. #11 lePasteur, 15.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Also, der Stand der Dinge:

    Ich führe den Befehl mit -i statt -e auf.
    Habe verschiedene Möglichkeiten probiert, und zwar:

    - square brackets herausgenommen, diesen Wert vorher in eine Variable gespeichert und diese eingesetzt

    - einmal mit direktem überschreiben, einmal mit Zwischenspeichern und mv (wobei es hierbei auch einen Fehler gab:

    mein Kommando sah so aus:

    exec sed -i "s/$key.*/$key $entry/" $CFG(CFG_FILE) > $CFG(CFG_FILE).x
    exec mv $CFG(CFG_FILE).x $CFG(CFG_FILE)

    Am Ende konnte ich nur eine leere Cfg-Datei vorfinden mit dem alten Dateinamen.

    - per externes Shell-Skript

    Ich hab ein Standalone-Skript geschrieben, das klappt wunderbar, nur im großen Programm funktioniert das nicht, es kommt immer wieder derselbe Fehler.


    Vielleicht allgemein was zum Programm, da ja die Standalone-Version mit Variablen funktioniert:

    Es wird beim Programmstart eine Konfigurationsdatei geladen und alle Attribute in verschiedene Variablen gesteckt. Der Benutzer soll durch ein Config-Fenster die Möglichkeit haben, die Configuration für eine Sitzung (d.h. bis das Prog geschlossen wird) oder im CFG-File zu speichern. Und gerade dieses Speichern klappt nicht, das Setzen der Werte schon.

    Der Ablauf ist folgender, wenn der Save-Button geklickt wird:
    Code:
    setzte CFG(CFG_FILE) auf den eingegebenen Pfad
    Lies die Datei ein und setze alle Attribute des neuen Files (eigene Proc)
    set chan [open $CFG(CFG_FILE)]
    set lineNumber 0
    while {[gets $chan line]>=0} {
     scan $line %s nkey
    if { [string equal $nkey $key]==1 } { # key steht hierbei für ein angegebens Attribut, mit dem die Proc aufgerufen wird
    set entry [.cfgwin.$path get] # path ist das zweite Attribut
    exec sed -i "s/$key.*/$key $entry/" $CFG(CFG_FILE)
    alternativ auch mit der .x-Variante
    
    Zu bemerken ist aber, dass ich vorher nicht die CFG-Werte neu eingelesen habe und das CFG-File auch nicht neu gesetzt habe. So hat es funktioniert, solange ich eine andere Datei angegeben habe, als die momentane CFG-Datei. Hier könnte eventuell der Knackpunkt sein, oder?

    Achja, die Rechte sind 755 bei allen Dateien, die ich getestet habe, einzulesen.

    Achja, das Standalone-Skript:
    Code:
    entry .test 
    button .b -text "Teste" -command { 
    set npgm [.test get]
    set test "s/INST_DICT.*/INST_DICT $npgm/"
    exec sed -i $test t.txt
    
    }
    
    pack .test .b -side left
    
    Klappt auch mit Variablen statt "INST_DICT".
     
  13. #12 floyd62, 15.03.2010
    Zuletzt bearbeitet: 15.03.2010
    floyd62

    floyd62 Routinier

    Dabei seit:
    01.05.2007
    Beiträge:
    309
    Zustimmungen:
    0
    Hi,

    sieht mir doch danach aus, als ob das Problem darin liegt, dass du über zwei Kanäle gleichzeitig deine CFG-Datei zu bearbeiten versuchst: auf der einen Seite liest du über den File-Deskriptor chan das Ding zeilenweise ein; sobald du ein Attribut findest, rufst du sed auf, und der verändert dann die Datei, die du gerade liest ... sportlich ... :)

    Mit der -i-Option bei sed (inline editing; gibts halt leider nicht auf allen Systemen) brauchst du das Konstrukt mit der temp-Datei natürlich nicht. Sonst passiert genau das, was du gesehen hast: sed erzeugt wahrscheinlich da intern schon eine solche temporäre Datei, schreibt seine Ergebnisse da rein, und überschrebit dann die alte mit der neuen. Wenn du jetzt noch den Output von sed benutzt (ist in dem Fall ja leer) und über die Originaldatei schiebst, bekommst du ein leeres Config-File.

    Wenn du sowieso die Datei schon zeilenweise liest, was spricht dagegen, einfach Zeile für Zeile in eine temp. Datei mitzuschreiben, dabei die Attribute gleich zu aktualisieren, und dann die Files entsprechend umzuubenennen? Spart das ganze sed-Gehampel ...

    Grüsse,
    A.
     
  14. Anzeige

    Vielleicht findest du HIER Antworten.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  15. #13 lePasteur, 15.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Dass ich da nicht früher drauf gekommen bin! Habs jetzt gelöst, wie du es gesagt hast, ist ja viel einfacher. Naja, wenn man sich einmal was in den Kopf gesetzt hat, entfallen schnell die anderen Möglichkeiten im Kopf...
    Jedenfalls funktioniert es jetzt.

    Vielen Dank!
    Grüße,
    Jan
     
  16. #14 lePasteur, 16.03.2010
    lePasteur

    lePasteur Jungspund

    Dabei seit:
    11.03.2010
    Beiträge:
    10
    Zustimmungen:
    0
    Ist zwar ein Doppelpost, aber anders sieht man es ja sonst nicht, oder?

    Gibt es einen Befehl oder Methode in Unix, die den absoluten Pfad eines momentan aufgerufenen Skriptes ausgibt?

    Beispiel:

    Ich befinde mich im Ordner "/root/ordner1/unterordner1", rufe von da aus das Skript "bsp.sh" im Ordner /root/Ordner1/unterordner2" auf.
    In diesem Skript gibt es eine Variable, die den Pfad des Skriptes "bsp.sh" zurückgibt. Je nachdem, wo also dieses Skript liegt, ändert sich auch der Variablenwert.

    Hat da wer eine Möglichkeit?
     
Thema:

[Tcl / Shell] Ändern einer Datei per vi - Änderungsdatum einer Datei erfassen