Що означає "{} \;" у команді find?


38

Іноді я бачу таку команду:

find . -name  * -exec ls -a {} \;

Мене попросили виконати.

Що {} \;тут означає?


2
-name *є зайвим.
Кевін

3
Також перегляньте пояснення для інших типів таких питань. Ось вихід для вашої команди. .
Glutanimate

10
-name *гірше зайвого. Оскільки *обоє не котирується, оболонка розширює його до списку імен файлів у поточній папці, при цьому помилки неправильно обробляються, що призводить до несподіваних результатів або повідомлення про помилку. В якості додаткового пункту, findє багато функцій, одна з яких полягає у переліку файлів; це дозволяє уникнути використання -exec. Наприклад, ви можете використовувати find . -printабо find . -ls. Нарешті, є два шляхи , щоб уникнути коми: або , як ви зробили з зворотним косими рисами, \;або процитувати: ';'. Використовуйте те, що вам більше комфортно.
Падді Ландау

Відповіді:


49

Якщо ви працюєте findз exec, {}розширюється до імені файлу кожен файл або каталог знайдений з find(так що lsу вашому прикладі отримує кожен знайдене ім'я файлу в якості аргументу - зверніть увагу , що він викликає lsабо будь-яку іншу команду вказується один раз для кожного знайденого файлу).

Точка з комою ;закінчується командою, виконаною exec. Його потрібно уникати, \щоб оболонка, яку ви запускаєте findвсередину, не сприймала її як свій особливий характер, а скоріше передає їй find.

Дивіться цю статтю для отримання більш детальної інформації.


Крім того, findпередбачає деяку оптимізацію exec cmd {} +- при виконанні подібного findспособу додає знайдені файли до кінця команди, а не викликає їх один раз на файл (щоб команда виконувалась лише один раз, якщо це можливо).

Різниця в поведінці (якщо не в ефективності) легко помітна при запуску ls, наприклад

find ~ -iname '*.jpg' -exec ls {} \;
# vs
find ~ -iname '*.jpg' -exec ls {} +

Якщо припустити, що у вас є деякі jpgфайли (з досить короткими шляхами ), результат - один рядок на файл у першому випадку та стандартна lsповедінка відображення файлів у стовпцях для останнього.


1
Я думаю , що було б корисно для вас , щоб контрастувати \;з +.
Кевін

Чим він відрізняється від find . -name * | ls -a -?
András Hummer

@DrH Справа не в тому, щоб оболонка не розширювала підстановку, а скоріше передала виразний знак find. Крім того, вихід lsу цьому випадку, мабуть, не залежить від вхідних даних - незалежно від того, що я використовую як фільтр find, він lsпросто відображає вміст робочого каталогу і це все. Перевірте, наприклад , find ~ -iname '*.jpg' -exec ls -a {} \;проти find ~ -iname '*.jpg' | ls -a.
moon.musick

@DrH або навіть echo 'foo' | ls -a.
moon.musick

@ moon.musick, я вважаю, що ви пропустили важливе значення -в своїй ls -a -команді під час тестування того, що запитував @ dr-h.
Daniel Llewellyn

21

З сторінки сторінки для findкомандиПіктограма manpage :

-exec command ;
              Execute  command;  true if 0 status is returned.  All following arguments to find are taken to be arguments to
              the command until an argument consisting of `;' is encountered.  The string `{}' is replaced  by  the  current
              file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it
              is alone, as in some versions of find.  Both of these constructions might need to be escaped (with a  `\')  or
              quoted  to  protect them from expansion by the shell.

Тож ось пояснення:

{}означає "вихід find". Як і в "що б не findзнайшли". findповертає шлях до файлу, який ви шукаєте, правда? Так {}замінює його; це заповнювач кожного файлу, який findзнаходиться в команді (взято звідси ).

\;Частина в основному говорить find«добре, я зробив з командою я хотів виконати».

Приклад:

Скажімо, я в каталозі, повному .txtфайлів. Потім я запускаю:

find . -name  '*.txt' -exec cat {} \;

Перша частина, find . -name *.txtповертає список .txtфайлів. У другій частині -exec cat {} \;буде виконуватися catкоманда для кожного знайденого файлу find, так cat file1.txt, cat file2.txtтощо.


4
Частину *.txtтреба цитувати як '*.txt'. Це тому, що якщо .txtу поточній папці є файли, оболонка розширить це, і ви отримаєте неправильні результати або повідомлення про помилку. find -name '*.txt' -exec cat {} \;
Paddy Landau

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