私は60 GBのメールを送信したメールアカウントを持っていますが、現在、昨年(2011年)のメールをアーカイブするためにメールクライアントを使用するのに苦労しています。
ターミナル経由で find を使用して、2011-01-01と2011-12-31の間のファイルを検索しようとしていますが、使用できません。
2つの日付の間のファイルを見つけるにはどうすればよいですか?
関連する場合、最終目標は、検出された各ファイルを日付間隔に一致するフォルダーに移動するバッチです。
次のスクリプトを使用できます。
#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
mv $i /moved_emails_dir/
done
2つの日付の間にファイルを検索する:
find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08
2010-10-07以降および2014-10-08以前のタイムスタンプを持つファイルのリストを返します
Bashは15分前から現在までのファイルを検索します:
find . -type f -mmin -15
15分前から現在までのタイムスタンプを持つファイルのリストを返します。
2つのタイムスタンプ間でファイルを検索する:
find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"
2014-10-08 10:17:00
と2014-10-08 10:53:00
の間のタイムスタンプを持つファイルを返します
Subv3rsion's および Eric Leschinski's の回答が示すように、-newermt
述語は、オペランドとして指定された日付(およびオプションの時間)よりも最近変更されたファイルを選択します。ファイルを見つけるには
srcdir
の任意の場所(つまり、サブディレクトリ、サブディレクトリなどを含む)destdir
...実行できます:
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;
-exec
式では、findは{}
の代わりに見つかったファイル名を渡します。 ;
は、実行するコマンドとその引数がすべて提供されたことを-exec
に示します(その特定の-exec
述語の引数の後に検索するために後続の式が渡される場合-この例については以下を参照してください)。 ;
は、\;
としてエスケープする必要があるため、シェルによって特別に解釈されません。 (\
がなければ、;
はfind
コマンド全体を終了し、改行と同じように機能します。このfind
コマンドはこの-exec
式の後には何もありませんが、;
引数を渡さないと構文エラーになります。)
ファイルを一覧表示するだけの場合(古い電子メールがどのように保存されているか、または他にどのファイルが存在するかわからない場合はお勧めします)、-exec
およびその右側のすべてを省略します。 (電子メールの場合、多くの場合、異なる日付の電子メールは same ファイルに保存されます。ここで質問に記載されている状況の場合、ファイルを移動する前に保存方法を調べることをお勧めします。 )それらの名前を印刷して移動したい場合は、-print
の前に-exec
を追加します。
mv -i
は、次の場合に発生するように、宛先でファイルが上書きされるたびにプロンプトを出します。
srcdir
の異なるサブディレクトリにあるファイルは、同じfind
操作中に既に移動されています。 or srcdir
操作中に、元のファイルが移動された後すぐにfind
のどこかに作成されたfind
が別のサブディレクトリを横断すると、見つけるのに十分です。rm
を呼び出す他の方法:重複した名前のファイルを処理する方法には他のオプションがあります。
-i
(つまり、mv {} destdir/
)がないと、mv
は通常、承認を求めるプロンプトを表示しませんが、宛先ファイルが読み取り専用の場合はそうします。 (mv
は、実行中のユーザーがファイルを所有している場合など、読み取り専用ファイルの上書きに成功することさえあります。)mv
に常に同じ名前のファイルを上書き(試行)させたい場合は、mv -f
を使用します。mv -n
を使用します。mv
は-b
および--backup
フラグを受け入れて、宛先に既に存在する同一の名前のファイルの名前を自動的に変更します。デフォルトでは、バックアップ名を生成するために~
が追加され、名前のファイルとバックアップ名のファイルが宛先に既に存在する場合、バックアップファイルは上書きされます。このデフォルトは、mv
の呼び出し時に渡されるオプションと環境変数によってオーバーライドできます。詳細および以下の例については、 man mv
を参照してください。すべてのファイルを移動するには、~
サフィックスを使用して重複する名前のファイルをバックアップし、.~n~
ファイルが既に存在する場合は番号付きの.~
サフィックスを使用します(何も上書きしないようにするため)。
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;
mv -n
を使用し、同じ名前の別のファイルがあったためにどのファイルが移動されなかったかを知りたい場合、おそらく、-exec
とその右側のすべてを使用せずに、元のfind
コマンドを再度実行するのが最善の方法です。これにより、名前が印刷されます。
また、元のfind .... -exec ...
コマンドを実行したために作成された一致するファイルの名前も出力しますが、このアプリケーションでは、変更時間が古いファイルを探しているため、通常は存在しません。 touch
およびその他のメカニズムを使用して、ファイルに実際の年齢よりも古い変更タイムスタンプを付けることは可能ですが、この場合、ユーザーの知らないうちに発生する可能性は低いようです。
mv -n
は、ファイルの移動を控えた場合、特別な exit code を報告せず、返しません。したがって、find
の実行中にスキップされたファイルをすぐに通知したい場合は、そのための別のステップを作成する必要があります。 1つの方法は次のとおりです。
find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
-exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;
おそらくいくつかのマイナーな技術的考慮事項:これは、mv
が宛先に存在するのとは異なる理由でファイルのコピーに失敗し、終了 報告成功の場合に誤って警告します。それはありそうにないが、私はそれが不可能だと確信していない。また、潜在的に 競合状態 が発生します:古いファイルの後の非常に短い時間の間に同じ場所に同じ名前の新しいファイルが作成された場合、実際のエラーがまったくないときに警告します削除されたかどうかを確認する前に移動されました。 (アプリケーションを考慮すると、どちらの問題も実際に発生することはないでしょう。)ファイルの移動後 before をチェックするように書き換えることができます。その後、競合状態は新しくなります。ソースファイルの代わりに宛先ファイルを作成しました。そして、find
またはmv
(または、[
はないはずですが)によって報告されたエラーと警告は 標準エラー に書き込まれますが、...skipped (exists in...
警告は 標準出力 に書き込まれます=。通常、両方が端末に表示されますが、スクリプトを作成している場合はこれが問題になることがあります。
読みやすくするために、このコマンドを2行に分割しました。そのように実行することも、\
と改行(つまり、改行)を削除することもできます。
find
コマンドはどのように機能しますか?find
述語は、 tests (-type
や-newermt
など)で戻り値に使用されるか、 actions (-print
や-exec
など) 頻繁にが副作用に使用されます。
演算子( and の-a
、 or の-o
など)が式の間に指定されていない場合、-a
が暗黙指定されます。 find
は、 and および or に対して 短絡評価 を使用します。 pq
(つまり、p -a q
)は、 p と q の両方の式が真である場合にのみ真になるため、 q p がfalseの場合、評価する必要はありません。私たちはこれらの用語でそれをしばしば考えませんが、これは評価されるべき後続のアクションまたはテストに対してテストが真実でなければならない理由です。たとえば、find
がディレクトリに来たとします。 -type f
をfalseに評価するため、その後すべてをスキップできます。
テストと同様に、アクションもtrueまたはfalseに評価されます。このようにして、-exec
は、実行されたコマンドが成功(true)または失敗(false)を報告して終了したかどうかを報告します。暗黙的な and に接続されたこの-exec
式のチェーンがあります。
-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;
これはファイルを移動しようとし、mv
が失敗を報告した場合、停止します。他の問題が原因で移動されなかった場合、正しくスキップされたファイルについて警告したくありません。
しかし、成功した場合は [
コマンド を実行します。 find
と同様に、[
は、引数として渡される独自の種類の式をサポートします。 [ -f {} ]
は、-f
の後のオペランド({}
の代わりにfind
によって渡される)が存在するかどうかを確認し(通常のファイル)、true/successまたはfalse/failureを返します。
(多くのコマンドの終了ステータスは、成功または失敗を示すものとして最も適切に解釈されますが、通常、[
の存在ステータスは、trueまたはfalseとして最も適切に解釈されます。)
[
がfalseを返した場合、ファイルはなくなっているため移動されたため、何もする必要はありません。ただし、[
がfalseを返した場合、ファイルはまだ存在しています。次に、find
は次の-exec
式を評価し、警告メッセージを出力します。
man find
および GNU Findutilsリファレンスマニュアルman mv
および GNU Coreutilsリファレンスマニュアル (特に 11.4 mv
:ファイルの移動(名前変更) )man \[
および 16.3テスト:ファイルタイプの確認と値の比較 Coreutilsドキュメント/usr/bin/[
)は、 シェルの[
組み込み ではなく、-exec [
を使用するときにfind
が実行するものです。