Cara membuat daftar file tanpa direktori, dan memfilter menurut nama (opsi ls)

42

Saya memiliki direktori bernama uploads. Ini berisi banyak file, ditambah beberapa subdirektori yang pada gilirannya berisi file.

Apakah ada cara saya dapat (dalam satu langkah) melakukan hal berikut:

  1. Daftarkan HANYA file dalam direktori unggahan root - Saya tidak ingin melihat nama subfolder atau isinya;

    dan

  2. JANGAN daftar file yang dimulai dengan t_

Saya tahu tentang -dbendera, tetapi itu tidak membuat saya mendapatkan apa yang saya inginkan.

EmmyS
sumber

Jawaban:

53

Ini terdengar seperti pekerjaan find.

  • Gunakan -maxdepthuntuk hanya mengembalikan direktori saat ini, jangan mencari di dalam subfolder secara berulang
  • Gunakan -type fhanya untuk mengembalikan file dan bukan direktori atau node perangkat atau apa pun
  • Gunakan kombinasi jika -notdan -nameuntuk menghindari file dengan nama yang tidak Anda inginkan

Mungkin datang bersama seperti ini:

find /path/to/uploads -maxdepth 1 -type f -not -name 't_*'
Caleb
sumber
Terima kasih! Saya cukup baru di CLI dan belum pernah menggunakan find sebelumnya. Saya pasti akan melihat lebih jauh ke dalamnya.
EmmyS
2
@EmmyS: Anda mungkin menemukan satu trik kecil lagi yang berguna di sini. @Gilles disebutkan menggunakan -exec ls -lG -- {} +dalam jawabannya untuk mendapatkan output menggunakan opsi tambahan untuk ls. Anda juga dapat menambahkan hanya -lske temuan ini untuk mendapatkan perkiraan cepat dan kotor dari tampilan rinci ls.
Caleb
18

GNU ls (yaitu perintah ls pada sistem Linux yang tidak tertanam dan Cygwin, juga tersedia di beberapa unit lain) memiliki opsi untuk menyembunyikan beberapa file, berdasarkan namanya. Tidak ada cara untuk mengabaikan direktori.

ls --hide='t_*' uploads

Pendekatan lain adalah membuat shell Anda melakukan pencocokan. Bash, ksh dan zsh memiliki pola negasi !(t_*)untuk mencocokkan semua file kecuali yang cocok t*; di bash fitur ini perlu dinyalakan shopt -s extglob, dan di zsh perlu dinyalakan setopt ksh_glob. Zsh juga memiliki sintaks ^t_*yang setara yang perlu dinyalakan setopt extended_glob. Ini masih tidak mengabaikan direktori. Zsh memiliki fitur tambahan yang memungkinkan untuk mencocokkan file tidak hanya dengan nama tetapi juga dengan metadata dan lainnya: kualifikasi global . Tambahkan (.)di akhir pertandingan untuk membatasi ke file biasa. Negasi ^adalah bagian dari sintaksis pencocokan nama, jadi ^t_*(.)artinya “semua file biasa tidak cocok t_*” dan bukan “semua file yang bukan file biasa cocok t_*”.

setopt extended_glob  # put this in your ~/.zshrc
ls uploads/^t_*(.)

Jika Anda menemukan diri Anda tanpa alat canggih, Anda dapat melakukan ini di unix dengan find. Ini bukan jenis yang biasanya Anda ketik di baris perintah, tetapi kuat dan tepat. Caleb telah menunjukkan bagaimana melakukan ini dengan GNU find . The -maxdepthpilihan adalah tidak portabel; Anda dapat menggunakannya -prunesebagai gantinya, untuk menghentikan findpengulangan secara mudah.

find uploads/* -type d -prune -o \! -type f -name 't_*' -print

Ganti -printdengan -exec ls -lG -- {} +untuk mengeksekusi lsdengan opsi favorit Anda pada file.

Semua perintah di atas menyembunyikan file dot (yaitu file yang namanya dimulai dengan a .). Jika Anda ingin menampilkannya, teruskan -Ake ls, atau tambahkan Dkualifikasi glob di zsh ( ls uploads/^t_*(.D)). Dengan find, Anda dapat menggunakan pendekatan yang berbeda untuk membuatnya hanya muncul satu tingkat ( findtidak memperlakukan file dot secara khusus). Ini hanya berfungsi jika Anda menjalankan finddi direktori saat ini.

cd uploads && find . -name . -o -type d -prune -o \! -type f -name 't_*' -print
Gilles 'SANGAT berhenti menjadi jahat'
sumber
3
Apakah Anda punya tugas harian? ;-) Saya selalu kagum pada panjang dan tingkat rincian jawaban Anda, bahkan untuk pertanyaan yang paling sederhana di sini di Unix SE! .. Tetap lakukan itu! :)
alex
Terima kasih! Sangat detail. Saya tidak tahu apakah saya memiliki "alat canggih" atau tidak saat ini; Saya menggunakan Mac di tempat kerja (meskipun Linux di rumah, jadi saya yakin ini akan berguna di beberapa titik.)
EmmyS
@EmmyS: Untuk kotak linux saya, saya -maxdepthharus menggunakan , tetapi masalah "portabilitas" mengacu Gilles adalah bahwa BSD find(juga ditemukan di OSX saya pikir) adalah hewan yang sedikit berbeda, jadi Anda mungkin perlu jawabannya juga. @Gilles: +1 untuk trik zsh!
Caleb
1
@Gilles: Beberapa komentar yang tidak begitu menarik tentang prunes muncul di pikiran, tetapi saya akan membiarkannya dengan hanya mengatakan bahwa ketika saya mucking sekitar pada sistem saya sendiri berapa kali pikiran " akan perintah ini bekerja jika saya berada di AIX, Solaris atau MINIX3 "kira-kira ... siaga ... Saya mengalami kesulitan mendapatkan pembacaan meter ... tampilan dibekukan 0.00.
Caleb
2
Bukankah Gnu lspunya --use-telepathypilihan? Itu cara tercepat untuk hanya menampilkan file yang Anda inginkan. Mungkin tidak portabel.
dubiousjim
8
ls -l /folder | grep ^- | awk '{print $9}'
Krayher
sumber
Apa yang ada $9dalam pernyataan ini?
EmmyS
3
@ Emmms Ini berarti bidang / kolom ke-9 dari output. Jawaban ini mencoba mengurai lsoutput .
jw013
print $ NF` akan lebih baik, IMO. $ NF berarti jumlah bidang, yang akan menjadi 9 dan merupakan penggunaan umum di AWK sebagai kesempatan yang baik untuk mengajar orang lain tentang $ NF.
Elijah Lynn
1
ls -l | grep -v ^d | grep name$
RICARDO MARMOLEJO GARCIA
sumber
Apa yang membuat solusi ini (yang membutuhkan banyak perintah dan pipa) lebih disukai find?
HalosGhost
Ini ringkas, mudah dibaca dan tetap dengan konvensi perintah ls. Saya merasa lebih mudah diingat daripada argumen perintah find. Untuk masing-masing dan pujian untuk opsi!
tkjef
0

Biarkan saya mencobanya lsdan menggunakan pipa:

ls  -l --hide='t_*'  uploads/ | grep -v ^d | tr -s ' ' | cut -d ' ' -f 9

katakanlah kolom terakhir adalah yang ke-9.

Y0NG
sumber
1
Bagaimana jika ada file dengan spasi?
jordanm
0

Jika masalah portabilitas -maxdepth menjadi perhatian, Anda dapat menggunakan:

ls -l uploads/ | awk '/^-/ && $9 !~/^t_/ {print $9}'

Saya bukan ahli, tetapi saya pikir ini harus berhasil. Saya kira itu terlihat sedikit samar, tetapi jika Anda berbicara awk, sebenarnya tidak. $ NF bisa digunakan sebagai pengganti $ 9. Anda juga bisa:

ls -l uploads/ | awk '/^-/' | awk '!/^t_/ {print $9}'

yang melakukan hal yang sama (tapi mungkin kurang efisien daripada yang sebelumnya ???).

Sebenarnya, setelah memikirkan postingan lain, sepertinya

ls -l --hide=t_* uploads/ | awk '/^-/ {print $9}'

adalah cara yang lebih pendek dan lebih jelas.

Seseorang tolong perbaiki saya jika saya salah. :-)

kkaszub
sumber
Parsing lsumumnya bukan ide yang baik . Trik awk Anda akan gagal dengan nama file dengan spasi putih di dalamnya misalnya.
Mat
@mat - Terima kasih atas koreksinya. Setelah membaca artikel yang Anda (dan jw013) tunjukkan, saya melihat bahwa ls tidak dapat dipercaya untuk menampilkan nama file yang benar. Bahkan jika saya menulis ulang kode awk untuk mencetak semuanya dari $ 9 hingga akhir baris (untuk memasukkan spasi putih), output ls ini mungkin masih salah. Ini mengecewakan dan harus diperbaiki IMO. Terima kasih lagi.
kkaszub
0

Saya menemukan cara-cara singkat ini:

ls -p uploads | grep -Ev '/'

atau

ls -pIt_* uploads | grep -v /
Radu Rădeanu
sumber
-1

Coba alias ini dan gunakan:

alias l='ls -hLlF'
Butiran
sumber
ls -hLlFtidak menunjukkan subdirektori dan itu menunjukkan file dimulai dengan t_. Jadi bagaimana ini menjawab pertanyaan?
Raphael Ahrens
Mungkin saya salah mengerti pertanyaan itu. ls -hLlF tidak akan menampilkan direktori target dari direktori yang ditautkan.
Granular
Kelihatannya begitu. Tetapi bukankah Anda sudah membaca jawaban lain untuk pertanyaan itu?
Raphael Ahrens
-1

Peasy mudah:

ls -l --hide 't_*' <absolute path to desired directory> | grep -v ^d

Penggali
sumber
(1) Jawaban ini sangat mudah, sudah diberikan sebelumnya. (2) Mengapa Anda percaya bahwa Anda perlu menentukan path lengkap ke direktori?
Scott
@Scott - ini adalah cara yang sangat cepat dan sederhana untuk mendapatkan solusinya. Jalur lengkap ditentukan untuk membuat jawabannya universal ...
Digger