MacからPCにすべての写真をエクスポートしました(Windows 11、PowerShellでUbuntuを実行)。エクスポートは元の作成日を削除し、フォーマットで各ディレクトリ(何千ものフォルダ)を作成しました。
April 1, 2004
Amsterdam, September 18, 2018
Anderson Arbor, March 24, 2011
日付で並べ替えたいです。これらの形式を次のように変更する方法についてのアイデアはありますか?
2004, April 1
2018, Amsterdam, September 18
2011, Anderson Arbor, March 24
または、より良い方法は次のとおりです。
2004-04-01
2018-09-18 Amsterdam
2011-03-24 Anderson Arbor
答え1
そしてzsh
:
$ autoload -Uz zmv
$ zmodload zsh/datetime
$ zmv -n '(|(*), )([^ ]## <1-31>, <->)' \
'$(strftime %F $(strftime -r "%B %d, %Y" $3))${2:+ $2}'
mv -- 'Amsterdam, September 18, 2018' '2018-09-18 Amsterdam'
mv -- 'Anderson Arbor, March 24, 2011' '2011-03-24 Anderson Arbor'
mv -- 'April 1, 2004' 2004-04-01
(-n
満足すれば削除(テスト実行))。
zmv
バッチ名を変更するための自動ロード可能なzsh関数。
2つのパラメータが必要です。
- グローバルモード(拡張はそれ自体で行われるため、引用符で囲む必要があります
zmv
)。 - 一致する各ファイルを置き換えるために文字列が評価されます。
置換で一致する各ペアは、...(...)
にあります。$1
$2
ここで、グローバルパターンは(|(*), )([^ ]## <1-31>, <->)
次のとおりです。
(x|y)
またはに一致するので、x
何でもy
一致する(|(*), )
か(2番目のペアにあるため、代替項目で*
終わる)で終了します。$2
(...)
", "
[^ ]
x##
1つ以上のx
sと一致するスペースを除くすべての単一文字と一致するため、スペースではなく[^ ]##
1つ以上の文字で構成されるすべてのシーケンスと一致します。<->
、境界なしの<x-y>
すべての数字と一連の10進数と一致します。
代替では、モジュールstrftime
に組み込まれている関数を使用してからキャプチャされた日付をzsh/datetime
解析(消費)し、フォーマットを再指定します。この組み込み機能はシンプルな標準インターフェースを提供し、それぞれフォーマットとアス機能を提供します。-r
$3
strftime()
strptime()
f
p
time
str
%F
%Y-%m-%d
日付形式を YYYY-MM-DD で表示する略語で、%B
完全月名、%d
特定の日付、%Y
年を表します。
コマンドの置き換えに使用する代わりに、langinfoから月名のリストを取得してから手動で月番号と形式に変換できます。strftime
これは、出力を得るために毎回プロセスをフォークすることを意味します。
zmodload zsh/langinfo
autoload -Uz zmv
months=( ${(v)langinfo[(I)MON_<1-12>]} )
# 1 2 3 4 5
zmv -n "(|(*), )(${(j[|])months}) (<1-31>), (<->)" \
'$5-${(l[2][0])months[(I)$3]}-${(l[2][0])4}${2:+ $2}'
どこ:
${(v)langinfo[(I)MON_<1-12>]}
キーが一致する連想配列の値に展開されますv
。$langinfo
MON_<1-12>
${(j[|])months}
j
oins 配列の要素です|
。$array[(I)$3]
に格納されているパターンに一致する配列要素の最大インデックスを返します$3
。${(l[2][0])string}
l
2
eftはsで文字列の長さを埋めます0
。
答え2
find
Perlrename
ユーティリティ(使用しているディストリビューションに応じてともprename
呼ばれる)を使用し、file-rename
perl-rename
日付::分析そして日付形式ライブラリモジュール。
これらのモジュールはPerlには含まれていないため、個別にインストールするか、Perlを介してインストールする必要があります。ファンコマンドラインツールまたは配布パッケージ。みんなここにいます。時間の日付Debian では .bundle からインストールできますsudo apt-get install libtimedate-perl
。他のディストリビューションでは、このパッケージの名前が何であるかわかりませんが、おそらく非常によく似ています。
ただし、Perlユーティリティとはまったく異なる互換性のない機能とコマンドラインオプションを持つユーティリティを混同しないでくださいrename
。rename
util-linux
それでも:
$ mkdir 'April 1, 2004' 'Amsterdam, September 18, 2018' 'Anderson Arbor, March 24, 2011'
$ find . -type d -print0 |
rename -n -0 'BEGIN {
use Date::Parse;
use Date::Format;
our $date_pattern = qr/[[:alpha:]]+ \d+, \d\d\d\d/;
};
our $date_pattern;
if (/^(.*\/)(.*)\b($date_pattern)$/) {
my ($p1, $p2, $d) = ($1, $2, $3);
my $t = str2time($d);
s/\b$date_pattern//;
$_ = sprintf("%s%s%s", $p1, time2str("%Y-%m-%d ",$t), $p2);
s/[, ]*$//;
}'
rename(./April 1, 2004, ./2004-04-01)
rename(./Amsterdam, September 18, 2018, ./2018-09-18 Amsterdam)
rename(./Anderson Arbor, March 24, 2011, ./2011-03-24 Anderson Arbor)
注:-n
これはこのオプションによるテスト実行です。必要に応じて動作することを確認したら、-n
それを削除するか、-v
詳細な出力に置き換えてください。
Date::Parse および Date::Format モジュールをロードし、$date_pattern
ブロック ( ) に変数を定義した後、BEGIN {}
この名前変更スクリプトは各ディレクトリ名を繰り返し、「月、年」パターンを一致させようとします。
成功すると、パス名の最後の要素を除くすべての要素が変数としてキャプチャ/抽出され、$p1
日付パターンの前にある最後のディレクトリ要素の「プレフィックス」部分が変数に入ります$p2
(これはオプションであり、欠落している場合は空の文字列です)。変数に入れます$d
。
その後、一致する日付は値(1970年1月1日午前0時から秒)$d
に変換され、この関数を使用して変数に割り当てられます。time_t
$t
str2time()
それから:
ディレクトリ名から日付パターンが削除されました。
sprintf
および関数は、をtime2str()
変更してファイル名全体を新しいパターンに合わせて変更するために使用されます$_
。この単純な割り当ては、
$_
Perlがどのように機能するかについて非常にシンプルで重要な事実を強調しますrename
。Perlで他の変数名(参照と検索)が指定されていない場合(演算子を含む)、その変数は
$_
ループのデフォルト変数として使用され、多くの関数と演算子のデフォルトの引数/オペランドとして使用されます。man perlvar
$_
s///
Perlの名前変更の場合、
$_
現在のパス/ファイルの名前を変更すると$_
名前が変更されます。変更すると$_
名前も変更されます。変わらないといけません。気づく
rename
に慣れる-f
このオプションを使用して、この操作を強制的に適用しない限り、既存のファイル名を上書きするようにファイルまたはディレクトリの名前を変更します。次に、最後のディレクトリ名からすべての末尾のスペースとカンマ(存在する場合)を削除します。
その他の注意事項:
変数は、スクリプトの起動時に一度だけ実行されるように
$date_pattern
ブロックに定義されています(stdinの各ディレクトリ名に対して1回ではありません)。BEGIN{}
2回使用されるため、変数として定義されます。変更する必要がある場合は、1つの場所でのみ変更することをお勧めします。 「1つ以上の英字、1つのスペース、1つ以上の数字、1つ以上のスペース、4つの数字」と定義されます。これは、サンプルのディレクトリ名と一致しますが、他のバリエーションが可能な場合は調整する必要があります。名前変更スクリプトの全範囲内で使用できるように宣言されます
our
(そうでない場合は、BEGINブロック内でのみ使用可能)。 Perlの名前変更スクリプトはstrict
Perlモードで実行されます(perldoc strict
詳細情報を参照)。qr
正規表現を引用する(おそらくパフォーマンスを向上させるためにプリコンパイルする)Perl引用演算子です。ここでのパフォーマンスはおそらく問題ではないでしょう。ここでは、主に一重引用符を使用することが1行以内で痛いという事実を解決するために使用しています。スクリプト。perldoc -f qr
詳細より。find ... -print0
andオプションrename
を使用すると、NULはファイル名の区切り文字として使用されるため、これはすべてのディレクトリ名、-0
改行、その他のスペースまたはシェルメタ文字(など)を含む;
ディレクトリ名にも適用されます&
。 NUL>
はただパス名に現れない文字です。
答え3
使用真珠rename
:
Time::Piece
Perlの中心に位置し、100%信頼できるDate::Parse
モジュールではなく、「魔法」よりもきちんとした方法と見なされます。
rename -n '
BEGIN{use Time::Piece}
my $d = localtime;
my $months_re = join "|", map { "$_\\w+" } $d->mon_list;
s/
($months_re)
\s+(\d+),\s+(\d{4})
/
my $d = Time::Piece->strptime("$1 $2, $3", "%B %d, %Y");
$d->strftime("%F")
/xe;
s/(.*),\s+(\d{4}-\d{2}-\d{2})/$2 $1/;
' ./*/
出力がうまくいったら削除してください-n
(別名)。dry-run
出力
rename(Amsterdam, September 18, 2018/, 2018-09-18 Amsterdam/)
rename(Anderson Arbor, March 24, 2011/, 2011-03-24 Anderson Arbor/)
rename(April 1, 2004/, 2004-04-01/)