Sortir output dari find -exec ls

14

Apakah mungkin untuk output find … -exec ls -ls ;diurutkan secara alpabetis, dengan nama file?

Ini adalah perintah cron saya:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

Perintah ini berfungsi baik, sebagian besar. Tetapi hasilnya tidak diurutkan dalam urutan yang berarti. Akan sangat membantu jika mereka akan disortir berdasarkan bidang nama file.

MaJ
sumber
1
Menggunakan zsh? ls -ls **/*(.)
Kevin
@ Kevin Tidak cukup - lsakan menyortir.
Gilles 'SO- stop being evil'

Jawaban:

14

Saya berasumsi bahwa nama file Anda tidak mengandung baris baru.

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

Menggunakan +alih-alih ;mengakhiri -exectindakan membuatnya lebih cepat dengan menumpuk doa ls. Anda dapat mengurutkan berdasarkan piping melalui sortperintah; katakan untuk mulai menyortir di bidang 10 (9 yang pertama adalah metadata: blok, izin, jumlah tautan, pengguna, grup, ukuran, dan 3 bidang tanggal / waktu). Opsi -nmemberi tahu lsuntuk menggunakan nilai numerik untuk pengguna dan grup, yang menghindari risiko nama pengguna atau grup yang mengandung spasi putih.

Atau, dengan zsh, Anda dapat pergi tanpa asumsi pada nama apa pun dengan menggunakan glob qualifiers untuk mengumpulkan dan mengurutkan file dan zargsmenjalankan lsbeberapa kali jika baris perintah terlalu panjang. Anda memang membutuhkan GNU ls(khususnya -fpilihannya) untuk menghindari pengurutan ulang dengan ls(pendekatan lain adalah meniru lsdengan zsh zstat).

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Terima kasih banyak! Menggunakan perintah pertama yang Anda kirim tidak mengurutkan. Apakah jumlahnya masih 10 jika saya menggunakan jalur yang lebih pendek? Misalnya, jika saya menjalankan perintah yang sama dari / home / setefgge, bukan dari public_html?
MaJ
@ MAJ 10 adalah jumlah bidang yang dilewati, ini tidak ada hubungannya dengan ukuran nama file.
Gilles 'SANGAT berhenti menjadi jahat'
Terima kasih. Saya menghargai bantuan Anda, dan juga bantuan yang diberikan orang lain. Saya menganggap masalah ini terpecahkan. Perintah cron saya sekarang menyortir file. Ini adalah pertama kalinya saya mengirim pertanyaan ke Stackexchange. Saya tidak melihat opsi "Soal". Jika ada di antara Anda yang tahu cara memposting ini diselesaikan, silakan lanjutkan. Terima kasih!
MaJ
@ MAJ Hal paling dekat kita harus menandai pertanyaan sebagai dipecahkan adalah menandai salah satu jawaban yang diterima. Hanya Anda, si penanya, yang dapat melakukannya. Untuk melakukan ini, klik tanda centang di sebelah jawaban yang paling membantu Anda. Jika Anda menerima jawaban, Anda akan mendapatkan 2 poin reputasi lebih banyak, dan setelah itu Anda akan dapat mengunggah posting; Anda dapat menghapus semua posting yang Anda temukan bermanfaat. Untuk informasi lebih lanjut, lihat halaman tur dan halaman bantuan tentang apa yang harus dilakukan ketika seseorang menjawab pertanyaan Anda .
Gilles 'SANGAT berhenti menjadi jahat'
1

Mengapa tidak mem-pipe hasil find melalui sort dan kemudian mengeksekusi ls untuk masing-masing baris?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done
groxxda
sumber
1

POSIX mengatakan ini tentang tanggal di ls -ldaftar ong:

The <date and time>lapangan harus memuat tanggal yang sesuai dan timestamp dari ketika file terakhir diubah. Di lokal POSIX, bidang harus sama dengan output dari perintah tanggal berikut:

date "+%b %e %H:%M"

... jika file telah dimodifikasi dalam enam bulan terakhir, atau:

date "+%b %e %Y"

Mempertimbangkan hal ini, dan memastikan bahwa jika ada baris baru dalam nama file, mereka diblender dengan benar dengan opsi yang juga ditentukan POSIX ls -q, relatif mudah untuk menyiapkan regex untuk lshasil tanpa findsama sekali:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grepuntuk itu dan Anda hanya akan mengembalikan garis yang berisi string yang mewakili tanggal hari ini atau kemarin. Perintah berikut menambah sedikit itu:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls opsi terdiri dari:

  1. -a kembalikan semua file dalam direktori - termasuk yang dimulai dengan a .dot
  2. -l daftar panjang
  3. -R daftar semua direktori anak secara rekursif
  4. -c menampilkan waktu modifikasi daripada waktu akses
  5. -qmengembalikan shell glob ?daripada karakter yang tidak dapat dicetak atau \tab dalam nama file

Hasil tersebut diteruskan ke |pipefile sedyang hanya cocok:

  1. Baris kosong sebelum nama path dan baris berikut
  2. Baris yang dimulai dengan - (d dengan kata lain - bukan untuk direktori) yang juga berisi date.
  3. Itu tidak mencetak garis pathname meskipun kecuali direktori yang mereka beri nama sebenarnya berisi file yang telah Anda filter.

Outputnya terlihat seperti ini:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

Ya, itu bahkan bekerja dengan LS_COLORS- yang mungkin merupakan prioritas rendah untuk Anda crontentu saja, tetapi, hei pilihan Anda terbuka.

Bagaimanapun, ini menawarkan beberapa keuntungan signifikan dibandingkan beberapa solusi lain yang mungkin.

  1. Pertama-tama find+ lsmelibatkan banyak pemanggilan - ini hanya melibatkan satu lsproses tunggal , dan inilah mengapa ia mampu mengurutkan segala sesuatu dengan andal - yang dilakukan secara default - dan sortjuga dibuat tambahan.

  2. Solusi apa pun yang melibatkan finddan sortdan lscukup banyak melakukan semua pekerjaan dua kali. lsdan findkeduanya akan menyelesaikan setiap pathname dan statsetiap file. lsdan sortkeduanya akan mengurutkan semua hasil. Mungkin lebih baik menggunakan satu saja ls.

  3. Maka tentu saja ada datedan sedsebagian dari jawaban ini. Yang penting untuk dicatat tentang itu adalah Anda melakukan bagian yang sulit dan mendapatkan regex pertama - dan hanya sekali - dan setelah itu Anda hanya memangkas satu daftar hasil daripada mengatakan, dapatkan hasil, dapatkan hasil, hasilkan hasil, hasilkan sortir dan hasil sortir.

  4. Ini tidak melanggar nama file yang mengandung baris baru, karena solusi lain mungkin akan melakukannya. Solusi ini memang memiliki peringatan sendiri - yang saya jelaskan selanjutnya - tetapi mereka kecil dan mudah ditangani. Menurut pendapat saya, ini adalah solusi paling kuat di sini.

Ada dua kasus di mana perintah di atas dapat menyebabkan masalah. Yang pertama melibatkan ?gumpalan dalam nama file - sementara itu sudah merupakan solusi yang lebih kuat daripada yang ditawarkan di sini, dan kemungkinan bahwa Anda akan menemukan ?sama sekali cukup kecil sendiri, ada kemungkinan menyelesaikan gumpalan tersebut dapat cocok dengan lebih dari satu nama file. Silakan lihat ini untuk informasi lebih lanjut tentang hal ini.

Kemungkinan lain melibatkan false positive - misalnya jika Anda memiliki nama file yang benar-benar cocok dengan datestring yang kami cari greptetapi itu tidak benar-benar dimodifikasi pada salah satu hari itu. Saya tidak mengandalkan itu menjadi masalah, tetapi, jika itu, tanyakan tentang hal itu dan saya mungkin dapat membantu Anda membuat regex lebih spesifik untuk menangani hal ini.

mikeserv
sumber
0

Anda benar-benar dapat menggunakan kombinasi find, xargs dan ls.

Berikut ini contoh perintah: find . -type f -print0 | xargs -0 ls -lt

  • find akan secara rekursif mencari semua file di bawah direktori saat ini.
  • xargs akan meneruskan daftar file ini ke lsperintah dalam satu panggilan tunggal (asalkan findmengembalikan kurang dari ARG_MAXfile).
  • ls -lt akan mengurutkan file-file ini berdasarkan waktu dan memformat output

Untuk mengambil sistem ARG_MAXAnda, Anda dapat mengetik:

$ getconf ARG_MAX
> 2621440
Maks
sumber
-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)
Walter A
sumber
1
lsmelakukan penyortiran sendiri, jadi menyalurkan output findmelalui sorttidak berguna. Selanjutnya perintah Anda mangles nama file yang berisi spasi putih (antara lain) dan akan gagal jika ada terlalu banyak nama file.
Gilles 'SANGAT berhenti menjadi jahat'