编辑后保留修改后的时间戳


20

对于特定文件夹中的文件,我希望vim绝对不要触摸“已修改”时间戳。

背景是我使用Bloxsom进行博客撰写,该博客使用纯文本文件~/bloxsom作为所有文章的来源。文章日期(因此出现顺序)基于文本文件的修改日期。我不希望每次修正拼写错误时都弹出文章。(我做了很多 ...:D)

到目前为止,vim会更改时间戳,原始戳记将永远丢失。可以,我想对系统上的大多数文件保持这种状态。但我不希望将其用于博客文件- touch如果需要,我可以始终提供该文件。

关于如何将Vim调整为这种行为的任何想法?


2
vim.wikia.com/wiki/…-您当然可以改用perl绑定
Ulrich Dangel,2012年

Answers:


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的包装,保存在我的.bashrc 中~/bin/vim-nomtime.pl并通过使用alias vim='~/bin/vim-nomtime.pl'

#!/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退出后才恢复印记,因此,如果我进行长时间的编辑并定期保存,文件vill将作为新文件弹出,直到退出vim。

  • 它在命令行上支持多个文件,但是以一种非常幼稚的方式-它仅检查其中的内容@ARGV是否是文件。这可能不适用于通配符(例如vim note-*.txt)或其他有趣的东西

  • 它不是防崩溃的,甚至可能不是HUP的(可以做到的)

  • ... wel,这是包装纸。(我的意思是,如果我们通过包装器解决了所有问题,那么在发生不良情况之前我们将拥有多少个包装器?)


2019年5月3日,我刚刚从2017年11月11日修改了一个文件,该文件既有我的修改,又保留了原始时间戳。:)
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âuShắ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)这几乎与五年前肖克·舒克(ShâuShắc)的回答相同。(2)假设用户vi一次只调用一个文件;它不适用于vi file1 file2。(3)不用说,如果用户使用切换到其他文件:e,将不会对其进行处理。
G-Man说'Resstate Monica''Mar

抱歉忘记参考,现在我在ShâuShắc的答案中添加了参考链接。
Steely Wing

关于问题#3,我认为如果您不在命令行中打开另一个文件,那就是您的问题。
Steely Wing

1
我的意思是,如果问题问“我如何使vim表现出我想要的方式?”,而您提供的功能看起来像是使vim表现出用户想要的方式,那么您有责任记录您的任何限制。回答。好吧,也许我的评论有点不公平,因为所有其他答案似乎都具有相同的局限性,据我所知,没有一个人提及它。我只是在审查您的答案,因为它是新的。我没有花很多时间在寻找其他答案。
G-Man说'Restore Monica''Mar

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版本datestattouch


0

使用上述某些概念,这是CSH的一种非常快速且肮脏的单行别名,为此目的可以使用“编辑”命令:

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以外的外壳,则可以相应地修改上面的示例。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.