たとえば、g.txtが2012年6月20日に最後に変更された複数のファイル(g.txtなど)を含むディレクトリがあります。
g.txtなどのすべてのファイルの名前をまとめて変更し、最後の変更日である2012年6月20日を最後に追加するにはどうすればよいですか?
答え1
これはgoldschrafeのラインバージョンです。
統計を使用しない
以前のバージョンのGNU日付
ファイル名のスペースを正しく処理してください。
ダッシュで始まるファイル名も処理します。
for f in *; do mv -- "$f" "$f-$(date -r "$f" +%Y%m%d)"; done
更新 2021-03-20
この質問に対する私の答えは何年も私を悩ませてきました(まあ、私が覚えているときだけ - 今日のように再び賛成票を得た日のみ)。それでついに更新するようになりました。上記の元の答えはまだ機能していますが、以下の更新された答えがより良いです。
良いどのバッチファイルの名前変更操作の場合は、以下を使用して実行する必要があります。真珠 rename
ループに逮捕されたシェルを使用する代わりにユーティリティです。
Perl名前変更ユーティリティは、実際には単純なs/search/replace/
正規表現操作(ほとんどの名前変更操作に十分です)から複雑な複数行スクリプトまで、Perlコードを使用してファイル名を変更できる特別なスクリプト言語です。
例えば
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を搭載したすべてのシステムにインストールする必要があります。IMO itと著者Graham BarrのDate::Parse
モジュール、しなければならないPerlコアモジュールライブラリの一部ですが、そうではないので、インストールするにはcpan
デプロイパッケージ(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
名前を変更する-n
(別名)「dry-run」オプションを使用します。--nono
要件を満たしていることを確認したら、削除してください-n
(または詳細な出力に置き換えてください)。-v
また注:他のPerlrename
スクリプトと同様に、コマンドラインおよび/または標準入力によって提供されるファイルの名前を変更できます。たとえば、現在のディレクトリとすべてのサブディレクトリにあるすべての.txtファイルの名前を変更するには、次の手順を実行します。
find . -type f -iname '*.txt' -print0 |
rename -0 --nofullpath -n '..........'
ただし、ここではrename
--nofullpath(別名-d
, --filenmame
, --nopath
) オプションを使用して、見つかったファイルパスのファイル名部分のみを名前変更します。この特別な場合には必要ありません(例の名前変更スクリプトはファイル名の末尾のみを変更するため)。ただし、パスとファイル名の名前を変更したくない場合は、一般的に良い考えです(たとえば、ファイル名's/ //g'
からスペースを削除する名前変更スクリプトは、パス内のすべてのスペースと先行しないファイル名を削除しようとすると--nofullpath
エラーが原因で失敗する可能性があります。
ついに:Perl名前変更スクリプト(FedoraやRedHatでFile::Rename
時々呼び出される、または)を名前変更という他のプログラムと混同しないでください。 prename
perl-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
現在のディレクトリにあるすべての(ワイルドカード)ファイルの名前を変更する高速で汚れたBashの1行filename.txt
:filename.txt-20120620
for f in *; do mv -- "$f" "$f-$(stat -c %Y "$f" | date +%Y%m%d)"; done
私は進取的なバッシュオタクがそれを破ることができる特別なケースを見つけると確信しています。 :)
明らかに、これはファイルの終わりに日付のように見えるものがすでにあるかどうかを確認するような望ましい効果を得ることはできません。
答え3
必須zshシングルライナー(オプションのコンポーネントのワンタイムロードを除く):
zmodload zsh/stat
autoload -U zmv
zmv -n '(*)' '$1-$(stat -F %Y%m%d +mtime -- $1)'
私たちはstat
組み込みを使用しますzsh/stat
基準寸法、しかもzmv
ファイル名を変更する機能。延長日の前に日付を追加する追加の項目(存在する場合)。
zmv -n '(*)' '$1:r-$(stat -F %Y%m%d +mtime -- $1)${${1:e}:+.$1:e}'
答え4
これは(goldschrafeのオネライナーベース)拡張CASのオネライナーバージョンです。等級、
つまり、日付/時刻プレフィックスを持つファイルに展開されます。まだ日付/時刻プレフィックスを持っていないユーザーにのみこれを実行してください。。
ユースケース:ディレクトリに新しいファイルを追加し、まだ日付/時刻プレフィックスが追加されていないファイルに日付/時刻プレフィックスを追加する場合に便利です。
for f in * ; do
if [[ "$f" != ????-??-??' '??:??:??' - '* ]]; then
mv -v -- "$f" "$(date -r "$f" +%Y-%m-%d' '%H:%M:%S) - $f" ;
fi;
done