Використання з'єднувачів після команди find


10

Я хочу, щоб мій bash надрукував "знайдено", лише якщо щось знайдено, використовуючи команду find. Але використання && не допомагає: навіть якщо нічого не знайдено, я надрукую "знайдений". Приклад:

$ pwd
/data/data/com.termux/files/home/test/test1/test4
$ ls
xaa  xab
$ find . -name xac && echo 'found'
found
$ find . -name xaa && echo 'found'
./xaa
found

Відповіді:


18

Ви можете зробити findдрук found:

find . -name xac -printf "found\n" -quit

-quitЗмусять find кинути палити після першого матчу , так що foundдрукуються тільки не більше одного разу.

На подібній темі в Unix & Linux ( make find fail, коли нічого не було знайдено ), я використовував grep -qzдля повернення ненульового статусу виходу, якщо findнічого не знайдено:

find /some/path -print0 -quit | grep -qz .

Які ви можете використовувати для побудови складених команд, використовуючи &&або if:

find /some/path -print0 -quit | grep -qz . && echo found

Мені довелося дивитись на це деякий час. /some/pathрозповідає, з чого почати шукати, але нічого не говорить про те, що шукати. Те саме у вашій відповіді. Що для мене працює find /some/path -name xac -print0 -quit | grep -qz . && echo found. Я щось пропустив?
Джо

@Joe, що тут важливо -print0 -quit. Що ви поставите перед цим, залежить від того, що ви хочете знайти. Я вирішив пропустити це тут.
муру

13

Відповідь Муру підходить і добре підходить для випадків, коли ми хочемо щось надрукувати, якщо файл знайдений. У загальному випадку, коли ми хочемо виконати зовнішню команду, наприклад echo, ми можемо використовувати -execпрапор.

$ find . -name 'xac' -exec echo "I found " {} \; -quit             
I found  ./xac

{}Частина проходить ім'я файлу в команді між -execі в \;якості аргументів. Зверніть увагу на \попереднє ;- це заважає помилковій інтерпретації оболонки ; в крапці з комою, яка закривається оболонкою, означає кінець команди, але, коли вона переходить з косою косою, оболонка буде розглядати її як текст, що переноситься на findкоманду, і знаходить команду, яка служить для закриття -execаргументів прапора.


Для побудови умовних умов if found do this; else do thatподібного роду ми могли б використовувати підменю команд $()та testкоманду (ака [):

$ [ "x$(find . -name 'noexist' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                              
not found

$ [ "x$(find . -name 'xac' -print -quit)" != "x" ] && echo "found" || echo "not found"                                                                                                  
found

Звертаючись до коментаря Дана

Ден у коментарях запитав:

Чи не відлуння "Я знайшов {}" краще, ніж відлуння "Я знайшов" {}? Можливо, для відлуння це добре, але якщо хтось скопіює команду та замінить ехо на іншу команду, у них можуть виникнути проблеми

Давайте розберемося спочатку з проблемою. Зазвичай в оболонках є поняття розділення слів, що означає, що нерозмінені змінні та позиційні параметри будуть розширені та розглядаються як окремі елементи. Наприклад, якщо у вас є змінна varі містить hello worldтекст, коли ви робите touch $varоболонка буде розбити його на два окремих пунктів helloі worldі touchбуде зрозуміло , що , як якщо б ви намагалися створити 2 окремі файли; якщо ви це зробите touch "$var", то оболонка буде розглядатись hello worldяк один блок, і touchстворить лише один файл. Це важливо, щоб зрозуміти, що це відбувається лише завдяки тому, як працюють снаряди.

Навпаки, findвід такої поведінки не страждає, оскільки команди обробляються самі findсобою і виконуються execvp()системним викликом, тому оболонки не задіяні. Хоча фігурні дужки мають особливе значення в оболонках, оскільки вони з'являються в середині findкоманди, а не на початку, вони не мають особливого значення для оболонки в цьому випадку. Ось приклад. Створимо кілька складних імен і спробуємо передати їх як аргумент statкоманді.

$ touch with$'\t'tab.txt with$' 'space.txt with$'\n'newline.txt

$ find -type f -exec stat -c "%F" {} \; -print                                                                                                                         
regular empty file
./with?newline.txt
regular empty file
./with space.txt
regular empty file
./with?tab.txt

Як бачите, отримання statскладних імен файлів ідеально добре find, що є однією з головних причин, чому його рекомендують використовувати в портативних сценаріях, і особливо корисно, коли ви переглядаєте дерево каталогів і хочете зробити щось із назви файлів, які потенційно можуть мати особливі символи в них. Тому не потрібно цитувати фігурні дужки для команд, виконаних у find.

Це вже інша історія, коли шкаралупа втягується. Іноді для обробки імені файлів потрібно використовувати оболонку. У цьому випадку цитування дійсно має значення, але важливо усвідомити, що це не проблема - це оболонка, яка робить розбиття слів.

$ find -type f -exec bash -c "stat {}" sh \;   
stat: cannot stat './with': No such file or directory
sh: line 1: newline.txt: command not found
stat: cannot stat './with': No such file or directory
stat: cannot stat 'space.txt': No such file or directory
stat: cannot stat './with': No such file or directory
stat: cannot stat 'tab.txt': No such file or directory

Тож коли ми цитуємо в оболонці , це спрацює. Але знову ж таки, це важливо для оболонки, а не find.

$ find -type f -exec bash -c "stat -c '%F' '{}'" sh \;                                                                                                                 
regular empty file
regular empty file
regular empty file

Не echo "I found {}"було б краще, ніж echo "I found " {}? Можливо, для відлуння це добре, але якщо хтось скопіює команду та замінить ехо на іншу команду, у них можуть виникнути проблеми.
Дан

@За темою було занадто довго, щоб обговорюватись у коментарях, тому я змінив свою відповідь. Будь ласка, дивіться
Сергій Колодяжний

1
Дякую за те, що нарешті змусив мене зрозуміти, для чого потрібен цей крапку з комою. Також чудове пояснення цитування.
Джо

1
Не очікував стільки деталей, як відповідь на мій коментар. Я дуже ціную це пояснення, дякую!
Дан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.