Perintah `find` tidak mengembalikan hasil saat menambahkan -exec

1

Ketika saya menjalankan findargumen ini, ia mengembalikan ribuan file:

steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users | wc
   3508   17479  245851
steven@nook:/mnt/station/media $

Ketika saya menambahkan -execargumen, berperilaku seolah-olah findtidak mengembalikan hasil dan kode pengembalian menunjukkan keberhasilan:

steven@nook:/mnt/station/media $ sudo find . -not -user steven -or -not -group users -exec echo {} \;
steven@nook:/mnt/station/media $ echo $?
0
steven@nook:/mnt/station/media $

(Tujuan saya adalah untuk menggunakan -exec chown -v steven:users {} \;hasil (karenanya sudo), tetapi saya menggunakan di -exec echo {} \;atas untuk menggambarkan masalah dengan lebih bersih dan mengesampingkan chownsebagai faktor yang berkontribusi.)

Saya menggunakan gnu find di bawah stock bash di Ubuntu Xenial:

steven@nook:/mnt/station/media $ find --version
find (GNU findutils) 4.7.0-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS(FTS_CWDFD) CBO(level=2)
steven@nook:/mnt/station/media $ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.2 LTS"
steven@nook:/mnt/station/media $ echo $SHELL
/bin/bash
steven@nook:/mnt/station/media $
Steven K.
sumber

Jawaban:

4

Itu karena operasi yang berdekatan mengikat dengan tersirat yang -andlebih eksplisit -or, dan karena, dari find(1)halaman manual, "Jika ekspresi tidak mengandung tindakan selain -prune, -cetak dilakukan pada semua file yang ekspresi benar."

Itu berarti findmelihat ekspresi pada contoh pertama Anda dan lihat

(-not -user steven) -or (-not -group users)

dan melakukan -printpada hasilnya, seperti yang Anda harapkan.

Find melihat contoh kedua Anda, sebagai

(-not -user steven) -or ((-not -group users) -and -exec echo {})

Itu harus menggema semua file milik pengguna steven dan bukan milik pengguna grup.

Solusinya adalah menambahkan tanda kurung di sekitar ekspresi Anda sebelum -exec:

sudo find . \( -not -user steven -or -not -group users \) -exec echo {} \;
garyjohn
sumber
Itu berhasil, terima kasih. Penjelasan yang bagus tentang bagaimana ia menguraikan pengelompokan implisit tanpa operator pengelompokan.
Steven K
Saya pikir jawaban Anda akan bermanfaat jika Anda secara eksplisit menyebutkan perilaku penting berikut ini expr1 -or expr2: " expr2tidak dievaluasi jika expr1benar". Butuh beberapa waktu untuk memahami mengapa Anda menulis "milik pengguna steven". Tidak begitu jelas.
Kamil Maciorowski
1

Anda perlu membuat dua koreksi pada baris perintah Anda.

Pertama, kawat gigi dari perintah exec perlu melarikan diri atau dikutip untuk melindungi mereka dari ekspansi oleh shell. Ini secara eksplisit disebutkan di halaman manual find .
Ada juga contoh di halaman manual untuk mengklarifikasi persyaratan ini.

   find . -type f -exec file '{}' \;

   Runs  `file'  on  every file in or below the current directory.  Notice
   that the braces are enclosed in single quote marks to protect them from
   interpretation as shell script punctuation.  The semicolon is similarly
   protected by the use of a backslash, though single  quotes  could  have
   been used in that case also.

Kedua, ruang lingkup & prioritas -orekspresi perlu diklarifikasi dengan tanda kurung (yang juga harus diloloskan).

Dengan koreksi, berikut ini akan berfungsi:

sudo find . \( -not -user steven -or -not -group users \) -exec echo '{}' \;

FWIW Saya lebih suka menyalurkan output dari perintah find, dan menggunakan xargs daripada berurusan dengan sintaks -exec.

find . -not -user steven -or -not -group users | xargs sudo echo
serbuk gergaji
sumber