Cara memindahkan file berdasarkan Tahun

14

Saya perlu memindahkan file berdasarkan satu tahun. Saya menggunakan findperintah

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

tetapi agar perintah ini berhasil dieksekusi, saya perlu tahu persis mtimesekarang 470 hanyalah sebuah tebakan. Berarti jika saya dapat memberikan tahun 2012 itu memberi saya file yang hanya terkait dengan 2012.

Jadi saya butuh saran tentang cara

Temukan file berdasarkan tahun mis. 2012 dan pindahkan ke direktori lain.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 
OmiPenguin
sumber
Apakah masuk akal untuk digunakan, -exec ls ... \;bukan -exec ... +? Apakah temuan Anda terlalu tua untuk itu? Dalam hal ini find ... -print0 | xargs -0 ls...akan jauh lebih cepat.
Hauke ​​Laging
Saya berharap pertanyaan-pertanyaan ini (dan jawaban) yang berhubungan dengan coreutils akan secara rutin menentukan apakah kita sedang berurusan dengan utiliti GNU atau BSD (atau lainnya).
labirin

Jawaban:

37

Anda ingin menggunakan -newermtopsi untuk find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

untuk mendapatkan semua file dengan waktu modifikasi pada tahun 2012.

Jika temuan Anda tidak mendukung, -newermtAnda juga dapat melakukan hal berikut untuk mencegah penggunaan perhitungan offset:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref
Anthon
sumber
1
-newermt flag tidak tersedia di perintah Find
OmiPenguin
Itu pasti versi lama dari temuan yang disertakan dengan RHEL Anda? Saya akan memberikan alternatif dalam jawaban untuk itu
Anthon
Ya yang ini 5.2
OmiPenguin
Saya menganggap itu adalah revisi dari RHEL, bukan dari find(Saya telah menemukan versi 4.4.2)
Anthon
1
Peralihan newermt tidak muncul di find sampai versi setelah v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
slm
5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls tidak masuk akal.

Hauke ​​Laging
sumber
1
-exec ls -llebih masuk akal, dan bahkan lebih saat pengujian.
CVn
@ MichaelKjörling finddapat mencetak semua yang lsbisa. OK, dengan satu pengecualian: melarikan diri / mengutip karakter yang tidak menyenangkan. Namun secara umum output dari finddapat diurutkan secara langsung. Panggilan tak berguna dari ls tidak membuat semuanya lebih cepat.
Hauke ​​Laging
Saya sangat sering menggunakan sesuatu yang sangat mirip (walaupun secara pribadi saya lebih suka -printatau mungkin -ls ) saat pengujian. Keuntungan menggunakan -exec ls {}adalah bahwa ia sudah mengeksekusi sesuatu yang eksternal untuk ditemukan . Jadi pada saat Anda beralih dari lske mv, perubahan yang sebenarnya minimal.
CVn
3

Menurut halaman manual, argumen untuk -mtime adalah jumlah hari yang Anda cari. Anda dapat menggunakan date +%juntuk menemukan jumlah hari sejak 1 Januari tahun berjalan.

Bratchley
sumber
2
Cara yang bagus. Menjadi sangat "nitpicky": -mtime -1: adalah file apa pun dalam 24 jam terakhir. Bukan hanya file dari kemarin (atau hari ini). Jadi, akan ada sedikit "tumpang tindih": jika Anda menentukan sudah 120 hari sejak 2012, dan hari ini adalah 15:45 ketika Anda meluncurkan skrip, Anda akan akhirnya memilih file hingga 31 Desember 15:45 ( dan bukan yang terakhir pada hari itu) ... Anda mungkin dapat menggunakan: nb_day - 1, dan kemudian "menyingkirkan" beberapa orang yang berasal dari tahun 2013 (yang dapat ditemukan oleh ls -l | grep -v, TAPI outputnya berbeda jika mereka hanya 1 hari saja ... banyak jebakan ...)
Olivier Dulac
Anda ingin menggunakan -daystartopsi ini jika ingin bekerja -mtime. Kalau tidak, Anda akan memiliki masalah dengan file di sekitar awal dan akhir tahun dengan cara apa pun yang Anda lakukan kecuali Anda menjalankannya tepat di tengah malam. Anda dapat melakukan offset dengan lebih akurat -mmindibandingkan dengan -mtimejika Anda dapat menemukan jumlah menit sejak tahun baru dengan mudah. Tetapi ada masalah yang sama dengan itu -mtime, hanya untuk file yang lebih sedikit (satu menit sekitar tengah malam tahun baru).
Anthon
1
Ya, membaca kembali halaman manual saya melihat bagaimana hal itu memecahnya menjadi berjam-jam jadi melakukan yang sederhana find -mtime $("date -+%j")mungkin tidak akan memberikan OP apa yang mereka inginkan. Saya meninggalkannya untuk anak cucu meskipun karena ini sepertinya blindspot bagi orang untuk jatuh ke dalam.
Bratchley
2

Anda dapat mencoba menggunakan kombinasi dengan perintah statdan / atau dateseperti pada baris satu berikut:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Dalam kedua kasus pendekatannya adalah dengan menggunakan dateperintah untuk mengekstrak tahun dari waktu modifikasi terakhir dari setiap file dan kemudian untuk membangun jalur dengan tahun ini. Perintah mkdir -pakan membuat jalur ini jika belum ada. Tentu saja Anda dapat menggunakan beberapa findopsi lain untuk mempersempit pencarian Anda.

woodengod
sumber
1

Jika Anda melakukan ini dari direktori kerja, Anda dapat melakukan ini sebagai gantinya:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Ini menyederhanakan banyak hal dan tidak menyebabkan tumpang tindih. Tetapi juga mengasumsikan bahwa file-file ini lebih tua dari 6 bulan, dan itu lsakan mencetak tahun bukan waktu yang tepat.

Untuk file yang lebih baru dari 6 bulan, Anda hanya perlu menggantinya dengan ini:

ls -l |awk '{ if ($6 == "May") print $9 }' 

atau yang serupa, tergantung pada bulan. Jika Anda ingin membuat daftar bulan untuk memindahkan file (atau jika Anda ingin membuat daftar selama bertahun-tahun) lakukan ini:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
Ernie
sumber