Conserver l'horodatage modifié après la modification


20

Pour les fichiers d'un dossier spécifique, je voudrais que vim ne touche jamais du tout à l'horodatage "modifié".

L'arrière-plan est que j'utilise Bloxsom pour les blogs, qui utilise des fichiers en texte brut ~/bloxsomcomme source de tous les articles. La date de l'article (et donc l'ordre d'apparition) est basée sur la date de modification du fichier texte. Je ne veux pas qu'un article s'affiche comme s'il était nouveau chaque fois que je corrige une faute de frappe. (J'en fais beaucoup ...: D)

Jusqu'à présent, vim change l'horodatage et le tampon d'origine est perdu pour toujours. C'est OK et je veux que cela reste ainsi pour la plupart des fichiers du système. Mais je ne veux pas cela pour les fichiers de blog - je peux toujours touchle fichier si j'ai besoin.

Des idées sur la façon de modifier vim dans ce comportement?


2
vim.wikia.com/wiki/… - vous pouvez bien sûr utiliser des liaisons perl à la place
Ulrich Dangel

Réponses:


22

Je ne pense pas que vim possède cette fonctionnalité. Une alternative consiste à modifier une copie et à définir l'horodatage de manière appropriée, par exemple:

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

Ou encore mieux:

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

7

Si vous avez besoin de vous amuser:

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

Remplacez le chemin par votre chemin de fichier réel


5

J'ai écrit un script Perl pour ça.

C'est un wrapper autour de vim, enregistré ~/bin/vim-nomtime.plet mis en service via alias vim='~/bin/vim-nomtime.pl'mon .bashrc.

#!/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->{$_}, $_;
    }
}

Quelques bonnes fonctionnalités:

  • prend en charge plusieurs noms de fichiers

  • prend en charge plusieurs répertoires "surveillés"

  • prend en charge le répertoire symlinked

  • peut être amélioré avec d'autres critères

dont la plupart pourraient probablement être également réalisés avec la version pure vim. Les inconvénients de cette solution par rapport à ma solution Pure-Vim souhaitée sont:

  • il restaure le tampon uniquement après la fermeture de vim, donc si je fais une longue édition et que je sauvegarde régulièrement, le fichier sera "pop-up" comme nouveau jusqu'à ce que je quitte vim

  • il prend en charge plusieurs fichiers en ligne de commande, mais d'une manière assez naïve - il vérifie uniquement si la chose @ARGVest un fichier. Cela ne fonctionnerait probablement pas avec des caractères génériques (par exemple vim note-*.txt) ou d'autres trucs amusants

  • ce n'est pas anti-crash, probablement même pas anti-HUP (cela pourrait être fait)

  • ... wel, c'est un emballage. (Je veux dire, si nous résolvions tout via le wrapper, combien de wrappers aurions-nous avant que quelque chose de mauvais ne se produise?)


Le 3 mai 2019, je viens de modifier un fichier du 11 novembre 2017 et il a à la fois ma modification et préserve l'horodatage d'origine. :)
jmort253

1

Ce court script conservera l'heure modifiée si un répertoire parent du fichier contient un .nomtimefichier:

#!/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

Essayez cette bashfonction (sur la base de la réponse de Shâu Sh )c )

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

Maintenant, nous pouvons éditer le fichier et conserver l'heure modifiée en utilisant ceci

vi-preserve-time file1.txt file2.txt

(1) Ceci est presque identique à la réponse de Shâu Shắc d'il y a cinq ans. (2) Cela suppose que l'utilisateur invoque viuniquement un seul fichier à la fois; ça ne marchera pas vi file1 file2. (3) Il va sans dire que si l'utilisateur bascule vers un autre fichier avec :e, il ne sera pas géré.
G-Man dit `` Réintègre Monica ''

Désolé d'oublier de faire référence, maintenant j'ai ajouté un lien de référence à la réponse de Shâu Shắc.
Steely Wing

À propos de votre question # 3, je pense que si vous ouvrez un autre fichier n'est pas dans la ligne de commande, c'est votre problème.
Steely Wing

1
Mon point est, si la question demande «Comment puis-je faire en sorte que vim se comporte comme je veux? répondre. D'accord, mon commentaire est peut-être un peu injuste, dans la mesure où toutes les autres réponses semblent avoir la même limitation, et aucune ne le mentionne, pour autant que je sache. Je revoyais simplement votre réponse parce qu'elle était nouvelle; Je n'ai pas passé beaucoup de temps à regarder les autres réponses.
G-Man dit `` Réintègre Monica ''

1

Il existe une option pour copier un horodatage à partir d'un autre fichier.

touch -m -r file_source file_target

Exemple:

[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

J'ai trouvé une excellente solution sur cette page Web , qui crée une fonction vim pour enregistrer le fichier actuel tout en préservant l'heure de modification existante, et lie cette fonction à la F4touche de fonction:

Cependant, j'ai trouvé que la fonction d'origine contient un bogue mineur, déclenchant l'avertissement suivant si F4est utilisé deux fois sur le même fichier, car vim devient confus lorsque l'heure de modification change:

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

Heureusement, cela est facile à résoudre: j'ai ajouté une commande "edit" à la fonction d'origine pour recharger le fichier après avoir restauré l'horodatage, donc vim sait quel temps de modification s'attendre à ce que le fichier ait.

Voici la fonction vim modifiée avec ce correctif de bogue, qui peut être ajoutée à ~/.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>

Remarque: Cette fonction repose sur les versions GNU de date, statet touch.


0

En utilisant certains des concepts décrits ci-dessus, voici un alias à une ligne très rapide et sale pour CSH qui rend une commande "edit" disponible à cet effet:

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

Vous pouvez facilement utiliser la variable d'environnement $ VISUAL ou $ EDITOR à la place de "vim". De cette façon, vous pouvez exécuter la commande suivante pour modifier les éditeurs par défaut

setenv VISUAL nano

Désormais, l'alias lui-même n'a plus besoin d'être redéfini pour accueillir différents éditeurs, ce qui le rend un peu plus portable. Si vous utilisez un shell autre que CSH ou TCSH, bien sûr, les exemples ci-dessus peuvent être adaptés en conséquence.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.