Bagaimana menemukan file antara dua tanggal menggunakan "find"?


21

Saya memiliki akun email yang telah melewati 60GB email, dan saat ini saya mengalami banyak masalah menggunakan klien email untuk mengarsipkan email tahun lalu (2011).

Melalui terminal, saya mencoba menggunakan find untuk mencari file antara 2011-01-01 dan 2011-12-31, tetapi tidak berhasil.

Bagaimana saya bisa menemukan file antara dua tanggal?

Jika relevan, tujuan akhir akan menjadi kumpulan yang akan memindahkan setiap file yang ditemukan, sesuai dengan interval tanggal, ke folder.


@EliahKagan Pada saat itu, jika ingatanku, nama yang diduplikasi tidak menjadi masalah. Meskipun demikian, jika Anda memberi tahu bahwa Anda punya waktu, informasi tambahan tentang subjek apa pun selalu dihargai :) Selain itu, saya telah memutakhirkan jawaban Anda karena memberikan wawasan ekstra tentang topik ini.
Zuul

@EliahKagan Dalam hal ini, saya mendorong Anda untuk memberikan jawaban dengan brankas-aman praktis yang telah Anda soroti :)
Zuul

Jawaban:


16

Anda dapat menggunakan skrip ini:

#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
  mv $i /moved_emails_dir/
done

6
Output dari findtidak boleh diproses dalam forloop shell seperti ini, kecuali ketika dijamin bahwa tidak ada file yang memiliki spasi kosong dalam namanya. -exec,, -execdiratau -print0 | xargsbiasanya digunakan sebagai gantinya; solusi lain yang mungkin, yang biasanya jauh lebih tidak diinginkan tetapi memungkinkan forloop untuk digunakan, adalah untuk sementara mengatur IFSsehingga ruang tidak dikenali sebagai pemisah bidang.
Eliah Kagan

@EliahKagan sehingga apa yang akan perintah terlihat seperti itu: Hanya mengganti finddengan exec? Maukah Anda menambahkan jawaban yang membahas penggunaan spasi .. ?? Sangat dihargai.
SherylHohman

3
@ SherylHohman Tidak, jangan gunakan execperintah. Gunakan findperintah dengan -exectindakan untuk menjalankan mv, atau apa pun yang Anda perlu jalankan, seperti yang dijelaskan dalam jawaban yang saya posting . Saat find... -execmenjalankan perintah Anda dengan nama path yang ditemukannya, itu tidak menggunakan shell, jadi spasi tidak memicu pemisahan kata atau globbing . (Anda mungkin ingin memposting pertanyaan baru tentang kasus spesifik Anda, atau untuk menanyakan apa yang ingin Anda ketahui.)
Eliah Kagan

@EliahKagan Maaf, saya salah membaca posting Anda - dan itu dari Anda ! Kamu luar biasa! Posting Anda sangat bagus .. dan terima kasih telah menanggapi, meskipun itu kesalahan saya sendiri dalam membaca !!
SherylHohman

40

Bash temukan file antara dua tanggal:

find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08

Mengembalikan daftar file yang memiliki stempel waktu setelah 2010-10-07 dan sebelum 2014-10-08

Bash temukan file dari 15 menit yang lalu hingga sekarang:

find . -type f -mmin -15

Mengembalikan daftar file yang memiliki stempel waktu setelah 15 menit yang lalu tetapi sebelum sekarang.

Bash temukan file di antara dua cap waktu:

find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"

Mengembalikan file dengan cap waktu antara 2014-10-08 10:17:00dan2014-10-08 10:53:00


10

Memindahkan file, dan meminta pengguna ketika ada nama duplikat:

Seperti yang ditunjukkan oleh Subv3rsion dan Eric Leschinski , -newermtpredikat memilih file yang dimodifikasi lebih baru dari tanggal (dan waktu opsional) yang ditentukan sebagai operandnya. Untuk menemukan file

  • di mana saja di srcdir(yaitu, termasuk subdirektori, subdirektori, dll.)
  • terakhir diubah pada (misalnya) September 2014
  • dan pindahkan kedestdir

... Anda dapat menjalankan:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;

Dalam -execekspresi, temukan melewati nama file yang ditemukan di {}. ;menandakan -execbahwa perintah yang akan dijalankan, dan argumennya, semuanya telah disediakan (dalam hal ekspresi selanjutnya dilewatkan untuk menemukan setelah -execargumen predikat tertentu - lihat di bawah untuk contoh ini). ;harus lolos karena \;tidak ditafsirkan secara khusus oleh shell. (Tanpa \, ;akan mengakhiri seluruh findperintah, bekerja sama dengan baris baru. Meskipun findperintah ini tidak memiliki apa-apa setelah -execungkapan ini , gagal melewati ;argumen masih merupakan kesalahan sintaksis.)

Jika Anda hanya ingin membuat daftar file - yang disarankan jika Anda tidak yakin bagaimana email lama disimpan atau file lain apa yang ada - hilangkan -execdan semuanya di sebelah kanannya. (Untuk email, seringkali email dari tanggal berbeda disimpan dalam file yang sama ; untuk seseorang dalam situasi yang dijelaskan dalam pertanyaan di sini, saya sarankan menyelidiki bagaimana mereka disimpan sebelum memindahkan file apa pun.) Jika Anda ingin mencetak nama mereka dan memindahkannya mereka, tambahkan -printsebelumnya -exec.

mv -i meminta kapan saja file akan ditimpa di tujuan, seperti yang akan terjadi jika:

  • file dengan nama yang sama ada dari cadangan sebelumnya, atau
  • file dengan nama yang sama tetapi dari subdirektori yang berbeda srcdirtelah dipindahkan selama findoperasi yang sama , atau
  • (paling tidak mungkin) file dengan nama yang sama dibuat di suatu tempat srcdirselama findoperasi yang sama , setelah dokumen asli dipindahkan tetapi tidak lama kemudian ditemukan setelah findmelintasi subdirektori yang berbeda.

Cara lain untuk memohon rm:

Anda memiliki opsi lain untuk bagaimana menangani file dengan nama duplikat.

  • Tanpa -i(yaitu, ), biasanya tidak meminta persetujuan, tetapi akan melakukannya jika file tujuan hanya-baca. ( Bahkan kadang-kadang bisa berhasil menimpa file read-only, seperti jika pengguna yang menjalankannya memiliki file tersebut.)mv {} destdir/mvmv
  • Jika Anda tidak ingin bahkan tingkat interaktivitas itu, dan ingin mvselalu (berusaha untuk) menimpa file yang bernama identik, gunakan mv -f.
  • Sebaliknya, jika Anda ingin melewatkan file sumber ketika sudah ada file tujuan dengan nama yang sama, gunakan mv -n.
  • mvmenerima -bdan --backupmenandai untuk secara otomatis mengganti nama file dengan nama identik yang sudah ada di tujuan. Secara default ~ditambahkan untuk menghasilkan nama cadangan, dan jika file dengan nama dan file dengan nama cadangan sudah ada di tujuan, file cadangan akan ditimpa. Default ini dapat ditimpa oleh opsi yang diteruskan saat memohon mv, dan oleh variabel lingkungan. Lihat man mvdetailnya, dan contoh di bawah ini.

Memindahkan file dan membuat cadangan jika nama duplikat:

Untuk memindahkan semua file, buat cadangan file dengan nama duplikat menggunakan ~sufiks, dan gunakan sufiks bernomor ketika file sudah ada (sehingga untuk menghindari menimpa apa pun), jalankan:.~n~.~

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;

Jika Anda melewatkan file dengan nama duplikat dan ingin tahu yang mana:

Jika Anda menggunakan mv -ndan ingin tahu file mana yang tidak dipindahkan karena ada file lain dengan nama yang sama, cara terbaik mungkin hanya dengan menjalankan findperintah asli lagi, tanpa -execdan semuanya di sebelah kanannya. Ini akan mencetak nama mereka.
Ini juga akan mencetak nama-nama file yang cocok yang dibuat sejak Anda menjalankan find .... -exec ...perintah asli , tetapi untuk aplikasi ini biasanya tidak ada karena Anda mencari file dengan waktu modifikasi lama. Dimungkinkan untuk memberikan file stempel waktu modifikasi yang lebih tua dari usia sebenarnya, dengan touchdan mekanisme lainnya, tetapi itu sepertinya tidak akan terjadi dalam kasus ini tanpa sepengetahuan Anda.

Mengetahui segera saat file dilewati karena nama rangkap:

mv -ntidak melaporkan, atau mengembalikan kode keluar khusus , ketika itu menahan diri untuk memindahkan file. Jadi, jika Anda ingin segera diberi tahu tentang file-file yang dilewati saat findberjalan, Anda harus membuat langkah terpisah untuk itu. Salah satu caranya adalah:

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 \; 

Beberapa pertimbangan teknis yang mungkin kecil: Peringatan ini salah jika mvgagal menyalin file karena alasan yang berbeda dari yang ada di tujuan dan keluar dari kesuksesan pelaporan . Sepertinya tidak mungkin, tapi saya tidak yakin itu tidak mungkin. Itu juga berpotensi menderita kondisi balapan : itu akan memperingatkan ketika tidak ada kesalahan sama sekali, jika file baru dengan nama yang sama dibuat di tempat yang sama selama waktu yang sangat singkat setelah file lama dipindahkan dan sebelum pemeriksaan untuk lihat apakah sudah dihapus. (Mempertimbangkan aplikasi, saya ragu kedua masalah itu akan benar-benar terjadi.) Bisa ditulis ulang untuk memeriksa tujuan sebelumnyamemindahkan file alih-alih setelah: maka kondisi balapan akan berhubungan dengan file tujuan yang baru dibuat alih-alih file sumber. Dan sementara kesalahan dan peringatan yang dilaporkan oleh findatau mv(atau [, meskipun seharusnya tidak ada) akan ditulis ke kesalahan standar , ...skipped (exists in...peringatan kami akan ditulis ke output standar . Biasanya keduanya muncul di terminal Anda, tetapi ini mungkin penting jika Anda membuat skrip.

Saya telah membagi perintah itu menjadi dua baris agar lebih mudah dibaca. Itu dapat dijalankan dengan cara itu, atau Anda dapat menghapus \dan baris baru (yaitu, baris istirahat).

Bagaimana cara findkerja perintah itu?

findpredikat dapat berupa tes (seperti -typedan -newermt), digunakan untuk nilai pengembaliannya, atau tindakan (seperti -printdan -exec), yang sering digunakan untuk efek sampingnya.

Ketika tidak ada operator (seperti -auntuk dan , -ountuk atau ) disediakan antara ekspresi, -atersirat. findmempekerjakan evaluasi hubung singkat untuk dan dan atau . (Yaitu, ) benar hanya jika ekspresi p dan q keduanya benar, jadi q tidak perlu dievaluasi jika p salah. Meskipun kita sering tidak memikirkannya dalam istilah ini, inilah mengapa tes harus benar untuk tindakan selanjutnya atau tes untuk dievaluasi. Misalnya, misalkan muncul pada direktori. Itu mengevaluasi ke false, sehingga dapat melewati semuanya setelah itu.p qp -a qfind-type f

Seperti halnya tes, tindakan juga mengevaluasi benar atau salah. Dengan cara ini, -execmelaporkan jika perintah yang dijalankan keluar melaporkan keberhasilan (benar) atau gagal (salah). Kami memiliki rantai -execekspresi ini yang terhubung dengan implisit dan :

-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;

Ini mencoba untuk memindahkan file, dan jika mvlaporan gagal, berhenti. Kami tidak ingin memperingatkan tentang file yang dilompati dengan benar jika ada masalah lain mengapa tidak dipindahkan.

Tapi jika berhasil, itu kemudian berjalan dengan [perintah . Seperti find, [mendukung jenis ekspresinya sendiri yang diteruskan sebagai argumen. [ -f {} ]memeriksa apakah operan setelah -f(diteruskan ke findtempatnya {}) ada (dan merupakan file biasa), dan mengembalikan benar / berhasil atau salah / gagal.
(Status keluar banyak perintah paling baik ditafsirkan sebagai menandakan keberhasilan atau kegagalan, tetapi [status yang ada biasanya ditafsirkan sebagai benar atau salah.)

Jika [dikembalikan false, maka file hilang, jadi dipindahkan, jadi tidak perlu melakukan apa pun. Tetapi jika [dikembalikan false, file tersebut masih ada. Kemudian findmengevaluasi -execekspresi berikutnya , yang mencetak pesan peringatan.

Bacaan lebih lanjut


Ketika saya mendapatkan waktu, saya berharap untuk menambahkan bagian tentang pertimbangan kinerja dan -exec ... +dengan mv -t, kadang-kadang segera.
Eliah Kagan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.