Bagaimana cara pipa ls ke grep, dan menghapus file yang difilter oleh grep?

33

Saya ingin menghapus beberapa paket di file rumah saya, tetapi nama file terlalu panjang ( google-chrome-stable_current_i386.deb). Jadi, saya memutuskan untuk menggunakan perintah ls|grep chrome|rmuntuk mem-pipe file ke grep untuk menyaring file chrome, dan kemudian menghapusnya. Itu tidak berhasil, jadi saya ingin melihat bagaimana saya bisa melakukan ini.

SpecialBomb
sumber
22
rm -i *chrome*.deb
Lambert
28
Secara umum saya tidak suka ketika orang memposting jawaban "jangan lakukan itu", tetapi ini adalah salah satu contoh terbaik dari masalah XY yang pernah saya lihat. Pertanyaan Anda yang sebenarnya adalah "bagaimana cara saya menghapus file dengan nama file yang panjang dengan cepat, tanpa mengetik semuanya", dan ada banyak cara bagus yang tidak melibatkan mengambil keluaran darils
Michael Mrozek
5
Cukup gunakan find- find . -name "*chrome*" -delete.
Boris the Spider
3
Dua sen saya sebagai pengguna StackExchange: di masa depan, ajukan pertanyaan Anda dengan cara yang lebih umum sambil memberikan detail tentang apa yang telah Anda coba. "Bagaimana cara menghapus file dalam folder dengan string tertentu dalam nama file?" mungkin cara yang lebih baik untuk mengungkapkannya. Kemudian Anda hanya bisa menambahkan, sebagai samping, bahwa Anda mencoba perpipaan lsmelalui grepke rmtapi tidak bisa mendapatkannya untuk bekerja. Dengan begitu Anda akan mendapatkan satu atau dua jawaban bagus tentang cara "benar" atau "termudah" untuk menyelesaikan tugas Anda daripada memaksa seseorang untuk memberi Anda jawaban yang baik tentang solusi yang tidak efisien.
Adrian

Jawaban:

56

Ini hampir membuatku meringis.

  1. Anda mungkin ingin berhenti mengarahkan senapan itu ke kaki Anda. Pada dasarnya segala jenis parsing lsakan menjadi lebih rumit dan rawan kesalahan daripada metode yang sudah ada seperti find [...] -execatau gumpalan .
  2. Kecuali seseorang memasang distro troll untuk Anda, shell Anda sudah Tabselesai. Cukup ketik rm googledan tekan Tab. Jika tidak segera selesai, tekan Tablagi untuk melihat daftar file yang cocok. Ketikkan lebih banyak karakter dari nama file untuk mempersempitnya sampai selesai, lalu jalankan perintah.
  3. Pipa ! = Parameter . Input standar adalah aliran data biner yang dapat diumpankan ke perintah secara asinkron. Parameter adalah string yang dipisahkan ruang yang dilewatkan satu kali dan hanya satu kali ke perintah saat menjalankannya. Ini sangat jarang dipertukarkan.
l0b0
sumber
1
Maaf jika sepertinya pertanyaan n00b. Saya tahu tidak apa-apa untuk digunakan secara umum, karena paket yang disebutkan adalah satu-satunya paket dengan "chrome" yang disebutkan di dalamnya. Oleh karena itu, menggunakan grep hanya akan memfilter satu file. Saya cukup baru di linux, dan saya sudah melakukan banyak skrip bash, tapi saya belum tahu semuanya: P. Keras, bung.
SpecialBomb
5
Tidak bermaksud keras, tetapi shell adalah lingkungan yang keras dan tak kenal ampun, tersembunyi di balik permukaan yang ramah pengguna. Melakukan sesuatu dengan aman itu cukup sulit, tidak masalah dengan aman atau bahkan dengan benar .
l0b0
2
@SpecialBomb Ini adalah satu-satunya jawaban yang benar. Menjelaskan cara membidik senapan dengan benar untuk memotong kaki seseorang dengan bersih, seperti jawaban lainnya, tentu saja bukan cara yang harus ditempuh. Berhati-hatilah dalam mengeksekusi secara membabi buta rm- ini mungkin satu-satunya cara yang lebih umum untuk menggoreng distro Anda.
Boris the Spider
@ BoristheSpider Heh, saya pasti sudah goreng Ubuntu dua kali menginstal driver kartu grafis AMD. Saya sudah mengajukan pertanyaan tentang itu. AMD sangat buruk, jadi saya bertanya apakah ada perbaikan umum atau metode bermain Linux yang lebih baik pada kartu AMD.
SpecialBomb
34

Anda juga dapat menggunakan perintah find dengan wildcard:

find . -maxdepth 1 -name '*chrome*' -delete

Perhatikan bahwa argumen "-maxdepth" memastikan bahwa find hanya berfungsi di direktori saat ini, dan tidak berulang ke subdirektori.

chander
sumber
1
Saran untuk perbaikan: (a) gunakan -inameuntuk nama file case-insensitive (b) pipa untuk xargsmenggunakan -print0flag for finddan -0flag for xargs. Penggunaan xargsmemungkinkan Anda untuk melakukan hal-hal seperti penghapusan "interaktif" (konfirmasi hapus foo?).
Christopher Schultz
3
Tidak perlu melakukan pipe ke xargs jika Anda menggunakan opsi -exec:find . -name '*chrome*' -exec rm -i {} +
Johnny
4
Bukankah ini juga akan menghapus secara rekursif ke dalam subdirektori? Anda mungkin perlu menentukan maxdepthuntuk menjadi 1.
Tyzoid
32

Anda punya ide yang tepat, hanya melewatkan beberapa detail. Karena Anda berurusan dengan daftar yang datang ke STDIN dan rmmengharapkan parameter, Anda perlu menggunakannya xargs.

Demikian:

ls | grep chrome | xargs rm

Harus memberi Anda apa yang Anda inginkan.

Catatan bahwa jika Anda ingin menghapus segala sesuatu selain chromeberkas, Anda hanya dapat menambahkan -vke greppernyataan.

Perhatikan bahwa, per jawaban lain untuk pertanyaan ini, ini mungkin cara yang buruk untuk mencapai apa yang ingin Anda capai.

John
sumber
Dengan -v, bukankah ini akan menghapus semuanya kecuali file yang cocok chrome? Saya tidak berpikir itu yang diinginkan OP ...
akivajgordon
Mencari lagi, Anda benar. OP ingin "memfilter file chrome", tetapi kemudian ingin menghapusnya.
John
Ini tampaknya rumit, dibandingkan dengan "rm -i chrome " sederhana
chander
5
Jawaban yang diterima berfungsi, tetapi lihat jawaban di bawah ini yang menjelaskan mengapa itu adalah ide yang buruk. (Memposting komentar ini di sini hanya demi mereka yang berhenti begitu mereka melihat tanda centang "diterima".)
Jim Davis
1
Ini, jawaban yang diterima "bekerja" hanya jika tidak ada nama file "aneh" di lsoutput. Nama file dengan spasi akan merusak ini. Ini juga berbahaya jika seseorang dapat membuat nama file dengan saus khusus di direktori tempat Anda menjalankan ini. Seperti yang telah ditunjukkan lebih dari satu orang, jangan parsing output dari ls !
Stephen P
11

Jangan pernah menguraikan output ls
Saran saya adalah untuk menghindari mengurai output ls [ 1 ] , bahkan lebih jika dalam hubungannya dengan delperintah. Ini karena berbagai alasan terutama terkait dengan karakter tak terduga dan tidak biasa yang diizinkan dalam nama file.

Bahkan ketika Anda harus berharap bahwa nama file milik paket Linux akan "berperilaku baik" , masalah ini tetap dapat muncul jika file lain ada di direktori yang sama tetapi Anda tidak tahu atau perhatikan.

Lebih baik digunakan find, ekspansi tab (mulai menulis nama dan tekan Tab), ekspansi nama file [ 2 ] sebagai *MyKey*...


Solusi cepat
Karena Anda ingin memilih semua paket (yang diakhiri dengan .deb) dengan "google" di dalamnya Anda dapat membangun permintaan Anda dengan wildcard * *google*.debdan melakukan yang sederhana

rm -i *google*.deb 

yang akan memilih setiap nama file dengan "google" di tengah yang akan selesai untuk .debhadir di direktori saat ini. Opsi -i(interaktif) akan meminta konfirmasi, kebiasaan yang baik ketika Anda menghapus file dengan ekspansi parameter.


Sebuah solusi yang dekat dengan filosofi usaha Anda.
Jika tujuan Anda adalah untuk membangun potongan perintah per bagian Anda, jadi Anda telah selesai ls, setelah ls | grep google, dan hanya setelah Anda memeriksa output Anda, Anda dapat menjalankannya dalam subkulit $(...)dengan

rm -i $(ls | grep google)

Cara yang lebih cepat dan lebih berbahaya [ 3 ] , adalah menggunakan!!

ls | grep google
rm -i $(!!)

yang akan menjalankan perintah terakhir yang selesai dalam riwayat Anda . Anda dapat melindungi diri dari kenyataan bahwa Anda tidak memiliki kontrol visual garis yang Anda akan mengeksekusi jika Anda telah mengaktifkan terlebih dahulu opsi shell histverifydengan shopt -s histverify.

Cepat
sumber
5
touch 0 1 2 3 4 5 6 7 8 9
find . -name \[0-9] -ok rm {} \;

< rm ... ./0 > ? y
< rm ... ./9 > ? y
< rm ... ./8 > ? y
< rm ... ./7 > ? y
< rm ... ./6 > ? y
< rm ... ./5 > ? y
< rm ... ./4 > ? y
< rm ... ./3 > ? y
< rm ... ./2 > ? y
< rm ... ./1 > ? y
^C

... gunakan -name '*c*.deb'atau pola lain yang cocok untuk Anda.

mikeserv
sumber
2

rmtidak menerima input dari stdin. Anda harus melakukan sesuatu sepertils google-chrome* | xargs rm

David King
sumber