Bagaimana cara memilih bidang / kolom dari output `ls -l`?

22

Tujuan saya tampak sederhana (setidaknya bagi saya). Saya ingin mengambil output ls -latau ls -lhdan memilih hanya satu bidang.

Saya mencari ini sebagai antipeluru mungkin, maksud saya, berasumsi bahwa nama file dapat memiliki jumlah ruang variabel, tidak semua bidang memiliki panjang yang sama, dll.

Poin bonus untuk memiliki skrip yang akan mengambil nama bidang (atau bahkan hanya nomor bidang), dan kemudian mengembalikan konten bidang.

Saya ingin berbalik

masukkan deskripsi gambar di sini

ke:

masukkan deskripsi gambar di sini

soando
sumber

Jawaban:

41

Coba ls -l | awk '{print $7}'.

awk memilih kolom sehingga sangat cocok untuk tugas ini.

Corey Whitaker
sumber
3
Seperti yang dijelaskan oleh @ormaaj: Jangan bergantung pada informasi yang tersedia di tempat-tempat tertentu dengan ls. The findperintah sangat membantu.
Paddy Landau
@ PaddyLandau Bagaimana cara saya menggunakan perintah find untuk mencetak ukuran file dalam megabyte seperti yang saya bisa lakukan dengan ls -l --block-size=M?
SurpriseDog
@Benjamin - lsPerintah ini bukan standar POSIX, jadi skrip yang bergantung pada lsdapat merusak sistem yang berbeda atau bahkan seiring waktu. Lihat jawabannya oleh @ormaaj di halaman ini untuk detail lebih lanjut. Salah satu cara untuk melakukan apa yang Anda minta adalah dengan Bash loop. Berikut ini sebuah contoh. for FILENAME in *; do FILESIZE=$(( $( stat --format=%s "${FILENAME}" ) / 1024 )); echo "${FILENAME}" ${FILESIZE}; done. Tentu saja, alih-alih echo, Anda akan menggunakan pemrosesan Anda.
Paddy Landau
@ PaddyLandau Saya baru saja selesai mem-pipkan output dari perintah find ... | xargs -d '\n' du -myang berfungsi dengan baik.
SurpriseDog
@Benjamin Anda mungkin ingin melihat -execopsi find.
Paddy Landau
17

Jangan parse ls . Gunakan GNU find. Atau jika portabilitas tidak penting stat(1),.

find . -maxdepth 1 -printf '%Td\n'

Untuk membaca data selain daftar nama file baris demi baris dan membelah menjadi beberapa bidang, lihat: BashFAQ / 001

Tidak ada metode untuk secara andal membaca daftar nama file yang dibatasi baris baru yang masuk akal dalam sebagian besar keadaan.

ormaaj
sumber
1

Anda dapat mengambil kolom tertentu di shell seperti:

ls -al | while read perm bsize user group size month day time file; do echo $day; done

atau awkseperti yang ditunjukkan dalam jawaban @Corey , cut -c44-45juga akan berfungsi setelah penyesuaian (karena lsmemiliki kolom yang diperbaiki), atau apa pun yang lain, namun masalah utama adalah bahwa itu tidak dapat diandalkan dan antipeluru (mis. pada Unix mungkin $6, tidak $7, dan itu perubahan tergantung pada argumen) sehingga tidak ramah mesin karena itu tidak disarankan untuk mengurai lsperintah sama sekali.

Yang terbaik adalah dengan menggunakan berbagai perintah yang tersedia seperti findatau stat, yang dapat memberikan opsi yang relevan untuk memformat output yang Anda butuhkan. Sebagai contoh:

$ stat -c "%x %n" *
2016-04-10 04:53:07.000000000 +0100 001.txt
2016-04-10 05:08:42.000000000 +0100 7c1c.txt

Untuk mengembalikan kolom modifikasi yang hanya beberapa hari, coba contoh ini:

stat -c "%x" * | while read ymd; do date --date="$ymd" "+%d"; done

Perlu dicatat bahwa GNU statdapat memiliki opsi yang berbeda untuk BSD stat, sehingga GNU tidak akan tahan antipeluru pada sistem operasi yang berbeda.

kenorb
sumber
1
+1 untuk menyebutkan bahwa ls tidak boleh diuraikan serta untuk penggunaan stat. dateNamun pengaturan salah. Anda harus menambahkan --date=$ymd, karena datedengan sendirinya akan mencetak hari ini, tetapi tujuannya di sini adalah untuk mengubah format tanggal file
Sergiy Kolodyazhnyy
The ls -la | cut -c32-33perintah total kejujuran adalah hanya benar-benar bisa diandalkan, bukan hanya karena perangkap mungkin dengan nama file, tapi hanya karena tergantung pada panjang dan pada file nama pengguna ukuran. The stat -c "%x" *.*perintah terlihat ok, tapi dengan menggunakan *.*Anda restricing hanya untuk nama file yang mengandung titik. Saya kira tujuannya adalah untuk menangkap juga file-file tersembunyi; dalam hal ini Anda harus memungkinkan globbing untuk dotfiles terlebih dahulu dan menggunakan *bukan *.*: shopt -s dotglob; stat -c "%x" * | [...].
kos
Ah dan apa Serg mengatakan juga, Anda harus menambahkan --date="$ymd"ke dateperintah, jika tidak maka akan mencetak hari saat bulan.
kos
Terima kasih atas komentarnya. Saya telah mengatasi masalah dan memberikan contoh awal yang lebih baik.
kenorb