ファイル名の末尾に変更日時のタイムスタンプを付けて、多数のファイルの名前を変更しますか?

ファイル名の末尾に変更日時のタイムスタンプを付けて、多数のファイルの名前を変更しますか?

たとえば、g.txt のようなファイルが多数含まれるディレクトリがあり、g.txt が最後に変更されたのは、たとえば 2012 年 6 月 20 日だとします。

すべてのファイル (g.txt など) の名前を一括変更して、末尾に最終更新日 2012 年 6 月 20 日を追加するにはどうすればよいでしょうか。

答え1

以下はゴールドシュラーフェのワンライナーのバージョンです:

  • 統計を使用しない

  • GNU dateの以前のバージョンで動作します

  • ファイル名内のスペースを正しく処理します

  • ダッシュで始まるファイル名にも対応

    for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done


2021-03-20更新

この質問に対する私の回答は何年も私を悩ませてきました (まあ、私がそれを思い出したときだけ - 今日のようにまた賛成票が入ったときだけ) ので、ついに更新します。上記の私の元の回答はまだ有効ですが、以下の更新された回答の方が優れています。

のようにどれでもバッチファイルの名前変更操作は、パール renameユーティリティであり、扱いにくいシェルの for ループではありません。

perl 名前変更ユーティリティは、実質的には、単純な正規表現操作 (ほとんどの名前変更タスクに十分) から複雑な複数行のスクリプトまで、任意の perl コードを使用してファイルの名前を変更できる特殊なs/search/replace/スクリプト言語です。

例えば

rename -n 'BEGIN {use Date::Format};
           die $! unless -f $_;
           next if (m/-\d{8}$/);
           my $ts=(stat($_))[9];
           my $dt=time2str("%Y%m%d",$ts);
           s/$/-$dt/;' *.txt

これにはperlとモジュールだけが必要ですDate::Format(このモジュールは非常に便利なので、perlがインストールされているシステムならどこにでもインストールしておくべきです。私の意見では、作者のGraham Barrのモジュールと一緒にDate::Parseすべきcpanこれは Perl のコア モジュール ライブラリの一部ですが、そうではないため、または Debian のパッケージのようなディストリビューション パッケージを使用してインストールする必要がありますlibtimedate-perl

ちなみに、このスクリプトは、ファイル名の末尾に日付 (つまり 8 桁) が既に含まれているように見えるファイルをスキップします。

または、ファイルのサフィックス(ある場合)の前に日付を置く、より洗練されたバージョンの場合:

rename -n 'BEGIN {use Date::Format; use File::Basename};
           die $! unless -f $_;
           my ($filename,$dirs,$suffix) = fileparse($_,qr/\.[^.]*/);
           next if (m/-\d{8}${suffix}$/);
           my $ts=(stat($_))[9];
           my $dt=time2str("%Y%m%d",$ts);
           s/${suffix}$/-${dt}${suffix}/;' *.txt

このバージョンには追加の要件はありません。これはFile::Basename、私が覚えている限り (少なくとも 10 年以上、おそらくそれ以上)、このモジュールが Perl の標準コア モジュールとして含まれていたためです。

注記:上記の両方のrenameスクリプトは、rename の-n(別名--nono)「dry-run」オプションを使用しているため、結果を適用する前にテスト/シミュレートできます。が目的どおりに機能することが確実になったら、 を削除します (または、詳細な出力の場合は に-n置き換えます)。-v

また、次の点にも注意してください:他の Perl スクリプトと同様にrename、コマンドラインや標準入力から指定されたファイル名を変更できます。たとえば、現在のディレクトリとすべてのサブディレクトリにあるすべての .txt ファイルの名前を変更するには、次のようにします。

find . -type f -iname '*.txt' -print0 | 
   rename -0 --nofullpath -n '..........'

renameところで、ここではの --nofullpath (別名-d--filenmame、 ) オプションを使用して--nopath、見つかったファイルパスのファイル名部分のみの名前を変更するようにしています。この特定のケースでは必要ありません (サンプルの名前変更スクリプトはファイル名の末尾のみを変更するため) が、ファイル名だけでなくパスも名前変更したくない場合は、一般的にこのオプションを使用することをお勧めします (たとえば、's/ //g'ファイル名からスペースを削除するような名前変更スクリプトは、 のないファイル名だけでなくパスのスペースも削除しようとするため--nofullpath、おそらくエラーが発生して失敗します)。

ついに:perl の名前変更スクリプト (別名File::Rename、またはprenameFedora と RedHat では 、または と呼ばれることもありますperl-rename) を、rename と呼ばれる他のプログラムと混同しないでください。 のみこの Perl ベースの名前変更ユーティリティは、上記のように任意の Perl コードを使用してファイルの名前を変更できますが、他の名前変更ユーティリティには異なる機能と異なる互換性のないコマンドライン オプションがあります。

正しい名前変更がインストールされているかどうかを確認できます:

$ rename -V
/usr/bin/rename using File::Rename version 1.13, File::Rename::Options version 1.10

実行可能ファイルはシステムによってprenameまたはperl-renameまたは と呼ばれる場合があります。これらを試し、正しい実行可能ファイル名を使用するように上記の例を調整してください。file-rename-V

答え2

filename.txt現在のディレクトリ内のすべての(glob)ファイルの名前を からに変更する、手っ取り早い Bash ワンライナーfilename.txt-20120620:

for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done

進取の気性に富んだ Bash オタクなら、きっとそれを破るエッジケースを見つけるでしょう。:)

明らかに、これは、ファイルの末尾に日付のようなものがすでにあるかどうかを確認するなどの望ましい処理は実行しません。

答え3

必須の zsh ワンライナー (オプション コンポーネントの 1 回限りの読み込みは除く):

zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'

組み込み関数statzsh/statモジュール、 そしてそのzmvファイル名を変更する関数。また、拡張子がある場合は、拡張子の前に日付を配置する追加機能もあります。

zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'

答え4

これはcasのワンライナーのバージョンです(goldschrafeのワンライナーに基づいており、次のように拡張されています)。冪等性

つまり、ファイルの先頭に日付と時刻を付けるようになり、日付と時刻のプレフィックスがまだない場合にのみこれを実行します

使用例: ディレクトリに新しいファイルを追加し、まだプレフィックスが付いていないファイルに日付と時刻のプレフィックスを追加する場合に役立ちます。

for f in * ; do
  if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
    mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
  fi;
done

関連情報