Bagaimana cara mendaftar setiap file dalam direktori kecuali yang memiliki ekstensi yang ditentukan?


28

Misalkan saya memiliki folder yang berisi .txt , .pdf , dan file lainnya. Saya ingin mendaftar file "lainnya" (yaitu, file tidak memiliki ekstensi .txt atau .pdf ). Apakah Anda punya saran tentang cara melakukan ini?

Saya tahu cara membuat daftar file yang tidak memiliki ekstensi yang diberikan. Misalnya, jika saya ingin mendaftar semua file kecuali file .txt , maka baik

find -not -iname "*.txt"

atau

ls | grep -v '\.txt$' | column

sepertinya berhasil. Tapi, bagaimana saya bisa mendaftar semuanya kecuali file .txt atau .pdf ? Tampaknya saya perlu menggunakan semacam logika "atau" di findatau grep.


2
Perlu diingat bahwa perilaku lsvs findvs globbing mungkin berbeda untuk dotfiles tersembunyi.
jw013

1
Satu hal yang perlu diingat: findakan melintasi subdirektori, seperti rekursif ls. Gunakan -maxdepth 1dengan finduntuk membuatnya berperilaku lebih seperti ls.
jw013

Jadi jangan rekursif, cukup daftarkan file dalam direktori saat ini?
daisy

Jawaban:


28

Dengan asumsi seseorang memiliki versi yang sesuai ls, ini mungkin cara paling sederhana:

ls -I "*.txt" -I "*.pdf"

Jika Anda ingin beralih di semua subdirektori:

ls -I "*.txt" -I "*.pdf" -R

8
lsOpsi GNU tidak portabel.
bahamat

4
lslagipula tidak benar-benar termasuk dalam skrip portabel, jadi saya berasumsi OP bertanya tentang penggunaan interaktif saja.
jw013

1
Mengapa ls tidak portabel? Apa yang harus saya gunakan?
Freedo

28

Temukan dukungan -o

find . ! '(' -name '*.txt' -o -name '*.pdf' ')'

Anda perlu tanda kurung untuk membuat hak diutamakan. Temukan melakukan banyak hal; Saya sarankan membaca halaman manualnya.

Anda juga dapat melakukan atau dalam grep(tapi sungguh, Anda tidak harus melewatkan output darils )

ls | grep -Ev '\.(txt|pdf)$' | column

1
Terima kasih! Mengapa saya tidak perlu menguraikan output ls?
Andrew

6
@Andrew pertama, karena rapuh (pertimbangkan nama file dengan baris baru di dalamnya — ya, itu nama file yang valid — temukan -print0 / -exec / -delete / dll. Hindari masalah itu); kedua, karena biasanya ada cara yang lebih mudah.
derobert

Selain halaman findmanual, saya dengan sepenuh hati merekomendasikan artikel tentang Unix Power Tools find, seperti docstore.mik.ua/orelly/unix3/upt/ch09_06.htm dan docstore.mik.ua/orelly/unix3/upt/ch09_12.htm
Wildcard

Hanya untuk membantu memecahkan kode pernyataan untuk manusia:find . NOT ( *.txt OR *.pdf )
wisbucky

12

Dengan bashglobbing yang diperluas (aktifkan dengan shopt -s extglob), glob !(*.txt|*.pdf)akan bekerja. Anda bisa mengirimkan glob ini langsung ke perintah apa pun yang mengambil argumen file, termasuk tetapi tidak terbatas pada ls.


1
+1 tetapi jika Anda memiliki subdirektori maka isinya akan terdaftar juga; gunakan -duntuk menghindari itu:ls -d !(*.txt|*.pdf)
legends2k

Terima kasih, saya benar-benar mencari sintaks untuk menerima banyak file, ini akan cocok di sini stackoverflow.com/questions/216995/…
Freedo

6

Dalam zshdengan extendedglob:

print -rl -- *~*.(txt|pdf)

atau

print -rl -- ^*.(txt|pdf)

Atau dengan kshglob(ya, itu ksh globbing bukan "bash extended globbing"):

print -rl -- !(*.txt|*.pdf)

Ingat juga bahwa mereka juga mengecualikan file dot.

ksh93 memiliki fitur FIGNORE(mis):

FIGNORE='@(.|..|*.txt|*.pdf)'
printf '%s\n' *

4
find /path/to/directory '!' -name '*.pdf' '!' -name '*.txt'

Ini setara dengan perintah dengan operator OR, karena hukum De Morgan .


3

Seperti yang disarankan oleh derobert, taruhan terbaik Anda adalah menggunakan find. Namun, Anda dapat sebenarnya menggunakan hasilnya dalam pipa dengan perintah lain.

GNU (dan beberapa BSD) findmendukung -print0predikat yang memerintahkannya untuk mencetak nama file yang diakhiri oleh karakter NUL , karakter mana yang tidak diperbolehkan dalam nama file dan menjamin tidak akan ada tabrakan. Perintah lain dapat diinstruksikan untuk menggunakan NUL sebagai pembatas input mereka.

Yang paling penting adalah GNU xargs, yang menjalankan perintah yang Anda tentukan dan meneruskannya daftar file sebagai argumen baris perintah. Anda ingin menjalankan xargs -r0bersama dengan find's -print0Misalnya:

find . -type f ! \( -name \*.pdf -o -name \*.txt \) -print0 | xargs -r0 ls -ld

Ini dengan aman mencetak daftar direktori panjang semua file pdf dan txt , termasuk yang memiliki spasi atau karakter yang tidak dapat dicetak dalam namanya.

Anda juga dapat menggunakannya dengan GNU tarsebagai berikut:

tar -zcf myarchive.tar.gz --null --files-from <(
  find . -type f ! -name \*.tar.gz -print0)

Ini membangun file tar.gz dari semua file yang namanya tidak diakhiri dengan .tar.gz

rsyncjuga menerima file dengan batas nol dengan -0parameter, seperti yang dilakukan beberapa orang lainnya. Tetapi xargslem yang biasanya Anda gunakan untuk tujuan semacam ini. Entah itu atau find's -execfitur.


Contoh tarperintah adalah yang baik. Namun, untuk sebagian besar tujuan, -execlebih cocok.
Wildcard

1

Jika Anda tidak memiliki subdirektori

ls !(*.pdf|*.txt)

juga harus bekerja!

Tapi

ls -I "*.pdf" -I "*.txt"

adalah cara yang umum.


0

Sebagai pelengkap, jika Anda menggunakan shell yang kompatibel dengan bash, Anda dapat menggunakan variabel GLOBIGNORE untuk mengecualikan resuts dari pencocokan pola. Dari pria itu:

   GLOBIGNORE
          A colon-separated list of patterns defining the set of filenames
          to be ignored by pathname expansion.  If a filename matched by a
          pathname  expansion  pattern also matches one of the patterns in
          GLOBIGNORE, it is removed from the list of matches.

Dalam kasus khusus Anda:

sh$ (GLOBIGNORE='*.pdf:*.txt'; ls -d *)

Harap dicatat saya menjalankan perintah itu sebagai sub-shell (menggunakan tanda kurung) agar tidak mengubah variabel lingkungan GLOBIGNORE dari shell interaktif saya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.