Сохранить измененную метку времени после редактирования


20

Для файлов в определенной папке я бы хотел, чтобы vim никогда не трогал «измененную» метку времени.

В качестве фона я использую Bloxsom для ведения блога, который использует текстовые файлы в ~/bloxsomкачестве источника всех статей. Дата статьи (и, следовательно, порядок появления) основана на дате изменения текстового файла. Я не хочу, чтобы статья всплывала, как будто она новая, когда я просто исправляю опечатку. (Я делаю много из них ...: D)

Пока что vim меняет метку времени, а оригинальная метка теряется навсегда. Это нормально, и я хочу сохранить это для большинства файлов в системе. Но я не хочу этого для файлов блога - я всегда могу touchфайл, если мне нужно.

Любые идеи о том, как настроить Vim в этом поведении?


2
vim.wikia.com/wiki/… Конечно, вместо этого вы можете использовать привязки Perl
Ульрих Дангел

Ответы:


22

Я не думаю, что у vim есть эта особенность. Один из вариантов - изменить копию и установить временную метку соответствующим образом, например:

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

Или даже лучше:

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

7

Если вам нужно повеселиться:

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

Замените путь на ваш фактический путь к файлу


5

Я написал Perl-скрипт для этого.

Это обертка вокруг vim, сохраненная ~/bin/vim-nomtime.plи введенная в использование через alias vim='~/bin/vim-nomtime.pl'мой .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->{$_}, $_;
    }
}

Некоторые хорошие функции:

  • поддерживает несколько имен файлов

  • поддерживает несколько "просмотренных" папок

  • поддерживает символическую директорию

  • может быть улучшен с другими критериями

большинство из которых, вероятно, также может быть достигнуто с чистой версией vim. Недостатки этого решения по сравнению с моим желаемым решением для чистой среды:

  • восстанавливает только штамп после того, как vim завершил работу, поэтому, если я буду долго редактировать и сохранять, файл будет всплывающим как новый, пока я не выйду из vim

  • он поддерживает несколько файлов в командной строке, но довольно наивно - он только проверяет, @ARGV является ли объект файлом. Это, вероятно, не будет работать с подстановочными знаками (например vim note-*.txt) или другими забавными вещами

  • это не доказательство аварии, вероятно, даже не доказательство HUP (это может быть сделано)

  • ... ну, это обертка. (Я имею в виду, если бы мы решили все с помощью обертки, сколько оберток у нас было бы до того, как случилось что-то плохое?)


3 мая 2019 года, и я только что изменил файл с 11 ноября 2017 года, и он имеет мою модификацию и сохраняет первоначальную метку времени. :)
jmort253

1

Этот короткий сценарий сохранит измененное время, если какой-либо родительский каталог файла содержит .nomtimeфайл:

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

Попробуйте эту bashфункцию (основываясь на ответе Shâu Shắc )

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

Теперь мы можем отредактировать файл и сохранить измененное время, используя это

vi-preserve-time file1.txt file2.txt

(1) Это почти идентично ответу Шау Шука, полученному пять лет назад. (2) Это предполагает, что пользователь запускает viтолько один файл за раз; это не сработает vi file1 file2. (3) Само собой разумеется, что, если пользователь переключится на другой файл :e, он не будет обработан.
G-Man говорит «Восстановить Монику»

Извините, что забыли упомянуть, теперь я добавил ссылку на ответ Shâu Shắc.
Steely Wing

По поводу вашего вопроса №3, я думаю, что если вы откроете другой файл не в командной строке, это ваша проблема.
Steely Wing

1
Моя точка зрения такова: если вопрос задает вопрос «Как я могу заставить vim вести себя так, как я хочу?», И вы предоставляете функцию, которая выглядит так, как будто vim ведет себя так, как хочет пользователь, вы несете ответственность за документирование любых ограничений ваших действий. ответ. Хорошо, возможно, мой комментарий немного несправедлив, поскольку все остальные ответы, похоже, имеют такое же ограничение, и никто из них не упоминает это, насколько я могу судить. Я просто просматривал ваш ответ, потому что он был новым; Я не тратил много времени на просмотр других ответов.
G-Man говорит «Восстановить Монику»

1

Существует возможность скопировать метку времени из другого файла.

touch -m -r file_source file_target

Пример:

[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

На этой веб-странице я нашел отличное решение , которое создает функцию vim для сохранения текущего файла при сохранении существующего времени модификации и связывает эту функцию с F4функциональной клавишей:

Однако я обнаружил, что исходная функция содержит небольшую ошибку, которая выдает следующее предупреждение, если F4дважды используется один и тот же файл, потому что vim запутывается при изменении времени модификации:

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

К счастью, это легко исправить: я добавил команду «edit» в исходную функцию, чтобы перезагрузить файл после восстановления временной метки, чтобы vim знал, какое время модификации ожидать от файла.

Вот модифицированная функция vim с этим исправлением ошибки, которую можно добавить к ~/.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>

Примечание: Эта функция зависит от GNU версии date, statи touch.


0

Используя некоторые из концепций, описанных выше, вот очень быстрый и грязный однострочный псевдоним для CSH, который делает команду «edit» доступной для этой цели:

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

Вы можете легко использовать переменную окружения $ VISUAL или $ EDITOR вместо "vim". Таким образом, вы можете выполнить следующую команду, чтобы изменить редакторы по умолчанию

setenv VISUAL nano

Теперь сам псевдоним не нужно переопределять, чтобы приспособить его к различным редакторам, что делает его несколько более переносимым. Если вы используете оболочку, отличную от CSH или TCSH, конечно, приведенные выше примеры можно соответствующим образом адаптировать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.