web-dev-qa-db-ja.com

最近変更されたファイルをvimで開く

次のコマンドが機能します

$ ls -1t | head -1
git_sync_log20180924_00.txt

$ vi git_sync_log20180924_00.txt

しかし、これはしません

$ ls -1t | head -1 | vi
Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: preserving files...
Vim: Finished.

どうすればこれを達成できますか(最近変更されたファイルをviで開きます)?

5
IceCreamToucan
vi -- "$(ls -t | head -n 1)"

(ファイル名に改行文字が含まれていないと想定しています)。

または、zshを使用する場合:

vi ./*(om[1])

または:

vi ./*(.om[1])

regularファイルのみを検討します。

vi ./*(.Dom[1])

hiddenファイルも考慮する(ls -Atを使用する場合と同様)。

これらは、ファイル名に含まれる文字またはバイト値に関係なく機能します。後者のGNU Shell&utilitiesと同等のものの場合、次のことができます。

IFS= read -rd '' file < <(
  find . ! -name . -Prune -type f -printf '%T@\t%p\0' | sort -zrn | cut -zf2-) &&
  vi "$file"
13

パイプライン構造では、xargsを次のように使用できます。

ls -1t | head -1 | xargs vi
6
mkc

lsの不安定な出力に依存しない、より強固なソリューションが必要な場合は、stat(1)を使用できます。ほとんどの実装では、sort(1)またはAwkスクリプトにフィードするタイムスタンプを含めることができるカスタム出力形式を指定する方法がいくつかあります。いくつかの例:

  • GNU coreutils:

    stat -L -c '%Y %n' -- *
    
  • bSD coreutils:

    stat -L -t '%s' -f '%Sm %N' ./*
    

その後、結果をソートしてフィルタリングできます。

  • coreutilsのみ:

    stat ... | sort -t ' ' -k 1,1 -n -r | head -n 1 | cut -d ' ' -f 2-
    

    最大値のみが必要な場合でも、入力全体を並べ替えるにはO(n log n)の時間が必要です。

  • awkの場合:

    stat ... | awk -F ' ' 'NR == 1 || $1 > m { m = $1; n = substr($0, length(m) + 2); } END{ if (NR) print(n); }'
    

    これは最大値を比較および更新するだけなので、O(n)時間で実行されます。

1
David Foerster