Behalten Sie den geänderten Zeitstempel nach der Bearbeitung bei


20

Für Dateien in einem bestimmten Ordner möchte ich, dass vim niemals den "geänderten" Zeitstempel berührt.

Der Hintergrund ist, dass ich Bloxsom für das Bloggen benutze, das reine Textdateien ~/bloxsomals Quelle für alle Artikel verwendet. Das Artikeldatum (und damit die Reihenfolge des Auftretens) basiert auf dem Änderungsdatum der Textdatei. Ich möchte nicht, dass Artikel auftauchen, wenn sie neu sind, wenn ich nur einen Tippfehler behebe. (Ich mache viele von ihnen ...: D)

Bisher ändert vim den Zeitstempel und der Originalstempel ist für immer verloren. Dies ist in Ordnung und ich möchte dies für die meisten Dateien auf dem System beibehalten. Aber ich möchte das nicht für die Blog-Dateien - ich kann immer touchdie Datei, wenn ich brauche.

Irgendwelche Ideen, wie Sie dieses Verhalten optimieren können?


2
vim.wikia.com/wiki/… - Sie können stattdessen natürlich auch Perlbindungen verwenden
Ulrich Dangel

Antworten:


22

Ich glaube nicht, dass vim diese Funktion hat. Eine Alternative besteht darin, eine Kopie zu ändern und den Zeitstempel entsprechend festzulegen, z.

cp -p post temp
vim temp
touch -r post temp
cp -p temp post

Oder noch besser:

touch -r post timestamp
vim post
touch -r timestamp post

7

Wenn du Spaß haben willst:

file=path; mtime=$(stat -c %y "$file"); vi "$file"; touch -d "$mtime" "$file"

Ersetzen Sie den Pfad durch Ihren tatsächlichen Dateipfad


5

Ich habe dafür ein Perl-Skript geschrieben.

Es ist ein Wrapper um vim, der in meinem .bashrc gespeichert ~/bin/vim-nomtime.plund verwendet alias vim='~/bin/vim-nomtime.pl'wird.

#!/usr/bin/perl
use strict;
use warnings;
use Cwd qw/ abs_path /;

my @dirs = qw( ~/blosxom /srv/relief/blosxom );

s/^~/$ENV{HOME}/ foreach @dirs;

# do we want to preserve stamp on this file?
sub fits {
    my $dir = abs_path($_[0]);
    my $fits = 0;
    foreach (@dirs) {
        my $preserved_dir = abs_path($_);
        $fits++ if $dir =~ m|^$preserved_dir|;
    }
    return $fits != 0;
}

# store original stamps
my $original_stamp;
foreach (@ARGV) {
    if ( -f $_ and fits($_) ) {
        $original_stamp->{$_} = (stat($_))[9];
    }
}

# run vim as you would
my $cmd = join ' ', 'vim', @ARGV;  
system($cmd) == 0
    or die "vim failed: $!";

# restore stamps if they have changed
foreach (keys %$original_stamp) {
    next unless -f $_;
    my $current_stamp = (stat($_))[9];
    unless ($current_stamp == $original_stamp->{$_}) {
        utime $original_stamp->{$_}, $original_stamp->{$_}, $_;
    }
}

Einige gute Eigenschaften:

  • unterstützt mehrere Dateinamen

  • unterstützt mehrere "überwachte" Verzeichnisse

  • unterstützt symlinked dir

  • kann mit anderen Kriterien erweitert werden

die meisten davon könnten wahrscheinlich auch mit einer reinen vim-version erreicht werden. Nachteile dieser Lösung im Vergleich zu meiner gewünschten Pure-Vim-Lösung sind:

  • erst nach dem beenden von vim wird der stempel wiederhergestellt. Wenn ich also lange bearbeite und regelmäßig speichere, wird die datei als neu angezeigt, bis ich vim beende

  • Es unterstützt mehrere Dateien auf der Kommandozeile, aber auf ganz naive Weise - es überprüft nur, ob es sich bei dem Objekt @ARGVum eine Datei handelt. Dies würde wahrscheinlich nicht mit Platzhaltern (zB vim note-*.txt) oder anderen lustigen Sachen funktionieren

  • es ist nicht crashsicher, wahrscheinlich nicht einmal HUP-sicher (das könnte getan werden)

  • ... na ja, es ist ein Wrapper. (Ich meine, wenn wir alles über einen Wrapper lösen würden, wie viele Wrapper hätten wir, bevor etwas Schlimmes passiert wäre?)


3. Mai 2019, und ich habe gerade eine Datei vom 11. November 2017 geändert. Sie wurde sowohl geändert als auch der ursprüngliche Zeitstempel beibehalten. :)
jmort253

1

Dieses kurze Skript behält die geänderte Zeit bei, wenn ein übergeordnetes Verzeichnis der Datei eine .nomtimeDatei enthält :

#!/bin/bash

dir="${1%/*}"
[ "$dir" = "$1" ] && dir=.
dir=$( readlink -f "$dir" )

nomtime=
while [ -n "$dir" ]; do
    if [ -f "$dir/.nomtime" ]; then
        nomtime=1
        break
    fi
    dir="${dir%/*}"
done

if [ "$nomtime" = 1 ]; then
    T=`tempfile`
    touch -r "$1" $T
fi

vi "$1"

if [ "$nomtime" = 1 ]; then
    touch -r $T "$1"
    rm $T
fi

1

Probieren Sie diese bashFunktion aus ( basierend auf Shâu Shắcs Antwort )

vi-preserve-time () {
    for file in "$@"; do
        local mtime=$(stat -c %y "$file")
        vi "$file"
        touch -d "$mtime" "$file"
    done
}

Jetzt können wir die Datei bearbeiten und die geänderte Zeit beibehalten

vi-preserve-time file1.txt file2.txt

(1) Dies ist fast identisch mit Shâu Shắcs Antwort von vor fünf Jahren. (2) Dies setzt voraus, dass der Benutzer jeweils vinur eine einzelne Datei aufruft . es wird nicht funktionieren vi file1 file2. (3) Wenn der Benutzer mit zu einer anderen Datei :ewechselt, wird dies selbstverständlich nicht behandelt.
G-Man sagt, dass Monica am

Tut mir leid, dass ich vergessen habe zu referenzieren, jetzt habe ich einen Referenzlink zu Shâu Shắcs Antwort hinzugefügt.
Steely Wing

Zu deiner Frage # 3, ich denke, wenn du eine andere Datei nicht in der Kommandozeile öffnest, ist es dein Problem.
Steely Wing

1
Mein Punkt ist, wenn die Frage „Wie kann ich vim dazu bringen, sich so zu verhalten, wie ich es möchte?“ Lautet und Sie eine Funktion bereitstellen, die so aussieht, als würde vim sich so verhalten, wie der Benutzer es wünscht, liegt es in Ihrer Verantwortung, alle Einschränkungen von Ihnen zu dokumentieren Antworten. OK, vielleicht ist mein Kommentar etwas unfair, insofern als alle anderen Antworten die gleiche Einschränkung zu haben scheinen und keiner von ihnen dies erwähnt, soweit ich das beurteilen kann. Ich habe gerade Ihre Antwort überprüft, weil sie neu war. Ich habe nicht viel Zeit damit verbracht, mir die anderen Antworten anzuschauen.
G-Man sagt, dass Monica am

1

Es besteht die Möglichkeit, einen Zeitstempel aus einer anderen Datei zu kopieren.

touch -m -r file_source file_target

Beispiel:

[oracle@es abc]$ ls -tlr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ echo "hi hi" > b
[oracle@es abc]$ ls -ltr
total 4
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
-rw-r--r--. 1 oracle oinstall   6 May 13 18:58 b
[oracle@es abc]$ touch -m -r aa.txt b
[oracle@es abc]$ ls -tlr
total 8
-rw-r--r--. 1 oracle oinstall   6 May  8 20:35 b
-rw-r--r--. 1 oracle oinstall 102 May  8 20:35 aa.txt
[oracle@es abc]$ cat b
hi hi

1

Ich habe auf dieser Webseite eine großartige Lösung gefunden , die eine vim-Funktion zum Speichern der aktuellen Datei erstellt, während die vorhandene Änderungszeit beibehalten wird, und diese Funktion an die F4Funktionstaste bindet :

Ich habe jedoch festgestellt, dass die ursprüngliche Funktion einen kleinen Fehler enthält, der die folgende Warnung auslöst, wenn F4dieselbe Datei zweimal verwendet wird, da vim verwirrt wird, wenn sich die Änderungszeit ändert:

WARNING: The file has been changed since reading it!!!
Do you really want to write to it (y/n)?

Glücklicherweise ist dies einfach zu beheben: Ich habe der ursprünglichen Funktion einen "Bearbeiten" -Befehl hinzugefügt, um die Datei nach dem Wiederherstellen des Zeitstempels neu zu laden, sodass vim weiß, welche Änderungszeit für die Datei zu erwarten ist.

Hier ist die modifizierte vim-Funktion mit dieser Fehlerbehebung, die hinzugefügt werden kann ~/.vimrc:

function! WriteSmall()
    let mtime = system("date -d @`stat -c %Y ".shellescape(expand('%:p')) . "`")
    write
    call system("touch --date='".mtime."' ".shellescape(expand('%:p')))
    edit
endfunction
map <F4> :call WriteSmall()<CR>

Hinweis: Diese Funktion basiert auf GNU - Versionen date, statund touch.


0

Unter Verwendung einiger der oben beschriebenen Konzepte ist hier ein sehr schneller und unsauberer Einzeilen-Alias ​​für CSH, der einen "Bearbeiten" -Befehl für diesen Zweck zur Verfügung stellt:

alias edit 'touch -r \!:1 /tmp/~mtime ; vim \!:1 ; touch -r /tmp/~mtime \!:1 ; rm /tmp/~mtime'

Anstelle von "vim" können Sie auch einfach die Umgebungsvariable $ VISUAL oder $ EDITOR verwenden. Auf diese Weise können Sie den folgenden Befehl ausführen, um die Standardeditoren zu ändern

setenv VISUAL nano

Jetzt muss der Alias ​​selbst nicht mehr neu definiert werden, um verschiedene Editoren zu unterstützen, was ihn etwas portabler macht. Wenn Sie eine andere Shell als CSH oder TCSH verwenden, können die obigen Beispiele natürlich entsprechend angepasst werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.