web-dev-qa-db-ja.com

編集後に変更されたタイムスタンプを保持

特定のフォルダ内のファイルについては、「変更された」タイムスタンプにまったく触れないようにしたいと思います。

背景は、私がブログに Bloxsom を使用していることです。これは、すべての記事のソースとして~/bloxsomのプレーンテキストファイルを使用します。記事の日付(したがって、表示される順序)は、テキストファイルの変更日に基づいています。タイプミスを修正するだけで、記事がnewであるかのようにポップアップを表示したくありません。 (私はそうしますそれらのロット...:D)

これまでのところ、vimはタイムスタンプを変更し、元のスタンプは永久に失われます。これは問題ありません。システム上のほとんどのファイルでこの方法を維持します。しかし、ブログファイルにはそれを使いたくありません。必要な場合はいつでもファイルをtouchできます。

Vimをこの動作に微調整する方法に関するアイデアはありますか?

21
Alois Mahdal

Vimにこの機能はないと思います。 1つの代替策は、コピーを変更してタイムスタンプを適切に設定することです。例:

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

またはさらに良い:

touch -r post timestamp
vim post
touch -r timestamp post
23
Thor

楽しみたいなら:

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

パスを実際のファイルパスに置き換えます

7
Shâu Shắc

そのためのPerlスクリプトを書きました。

これはvimのラッパーで、~/bin/vim-nomtime.plに保存され、.bashrcの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バージョンでも実現できます。このソリューションの欠点は、希望するpure-vimソリューションと比べて次のとおりです。

  • スタンプのみを復元します変更後 vimが終了したため、長い編集を行って定期的に保存すると、vimを終了するまで、ファイルは新規として「ポップアップ」されます

  • コマンドラインで複数のファイルをサポートしますが、非常に単純な方法で@ARGV上のものがファイルであるかどうかのみをチェックします。これはおそらくワイルドカード(例:vim note-*.txt)またはその他の面白いものでは機能しません。

  • 耐衝突性ではなく、おそらくHUPにも対応していません(それは可能です)。

  • ...それはラッパーです。 (つまり、ラッパーを介してすべてを解決した場合、何か問題が発生する前にラッパーはいくつあるでしょうか?)

5
Alois Mahdal

別のファイルからタイムスタンプをコピーするオプションがあります。

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
user352752

私は this web page で素晴らしい解決策を見つけました。これは、既存の変更時間を維持しながら現在のファイルを保存するvim関数を作成し、この関数を F4 ファンクションキー:

ただし、元の関数に軽微なバグが含まれていることがわかりました。 F4 変更時刻が変更されるとvimが混乱するため、同じファイルで2回使用されます。

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

幸いなことに、これは簡単に修正できます。タイムスタンプを復元した後でファイルをリロードするために、元の関数に「編集」コマンドを追加したので、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 datestatのバージョンに依存し、 touch

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
Xiè Jìléi

この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
Steely Wing

上記の概念のいくつかを使用して、CSHの非常に速くて汚い1行のエイリアスを以下に示します。これにより、この目的で「編集」コマンドを使用できるようになります。

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

"vim"の代わりに$ VISUALまたは$ EDITOR環境変数を簡単に使用できます。これにより、次のコマンドを発行してデフォルトのエディターを変更できます

setenv VISUAL nano

エイリアス自体は、さまざまなエディターに対応するために再定義する必要がないため、多少移植性が高くなります。もちろん、CSHまたはTCSH以外のシェルを使用する場合は、上記の例を適宜変更できます。

0
Leslie Krause