`find` dengan beberapa` -name` dan `-exec` hanya menjalankan kecocokan terakhir dari` -name`

74

Saat saya menggunakan

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt"

ia menemukan semua jenis file. Tetapi ketika saya menambahkan -execdi akhir:

find . -type f -name "*.htm*" -o -name "*.js*" -o -name "*.txt" -exec sh -c 'echo "$0"' {} \;

sepertinya hanya mencetak .txtfile. Apa yang saya lakukan salah?

Catatan: menggunakan MINGW (Git Bash)

jakub.g
sumber
Petunjuk: perintah pertama juga akan mencetak direktori yang namanya cocok *.js*atau *.txt.
Wildcard

Jawaban:

98
Temukan . -type f -name "* .htm *" -o -name "* .js *" -o -name "* .txt"

kependekan dari:

Temukan . \ (\ ( -type f -a -name "* .htm *" \) -o \
          \ ( -nama "* .js *" \) -o \
          \ ( -nama "* .txt" \) \
       \) -sebuah cetak

Yaitu, karena tidak ada predikat tindakan yang ditentukan (hanya kondisi ), suatu -printtindakan ditambahkan secara implisit untuk file yang cocok dengan kondisi tersebut.

(dan, omong-omong, itu akan mencetak .jsfile tidak biasa ( -type fhanya berlaku untuk .htmfile)).

Sementara:

Temukan . -type f -name "* .htm *" -o -name "* .js *" -o -name "* .txt" \
  -exec sh -c 'echo "$ 0"' {} \;

kependekan dari:

Temukan . \ ( -type f -a -name "* .htm *" \) -o \
       \ ( -nama "* .js *" \) -o \
       \ ( -nama "* .txt" -a -exec sh -c 'echo "$ 0"' {} \; \)

Karena find(seperti dalam banyak bahasa), AND ( -a; implisit ketika dihilangkan) memiliki prioritas di atas OR ( -o), dan menambahkan predikat tindakan eksplisit (di sini -exec) membatalkan -printtindakan implisit yang terlihat di atas. Di sini, Anda ingin:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) \
  -exec sh -c 'echo "$0"' {} \;

Atau:

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c '
   for i do
     echo "$i"
   done' sh {} +

Untuk menghindari menjalankan satu shper file.

Stéphane Chazelas
sumber
Dalam beberapa penggunaan sh -c, Anda perlu menambahkan argumen zeroth untuk sh (meskipun pada yang lain Anda sudah memasukkannya).
James Youngman
1
Itu jawaban yang bagus!
Marinos An
30

Itu adalah tanda kurung. Tambahkan tanda kurung eksplisit.\( \)

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -exec sh -c 'echo "$0"' {} \;

atau menggunakan xargs (Saya suka xargs saya merasa lebih mudah, tetapi tampaknya tidak portabel).

find . -type f \( -name "*.htm*" -o -name "*.js*" -o -name "*.txt" \) -print0 | xargs -0 -n1 echo
ctrl-alt-delor
sumber