Як передавати список файлів, повернутих командою find до кота, щоб переглянути всі файли


204

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

Відповіді:


340
  1. Перехід до іншого процесу (Хоча НЕ БУДЕ виконати те, що ви сказали, що намагаєтесь зробити):

    command1 | command2
    

    Це надішле висновок command1 як вхід command2

  2. -execна a find(це зробить те, що ви хочете зробити - але конкретно для find)

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

    (Все між findі -execє предикатами знаходження, які ви вже використовували. {}Замінить конкретний файл, який ви знайшли в команді ( cat {}в даному випадку); команду \;слід закінчити -exec.)

  3. відправити вихід одного процесу як аргументи командного рядка на інший процес

    command2 `command1`
    

    наприклад:

    cat `find . -name '*.foo' -print`
    

    (Зверніть увагу , це зворотні лапки не регулярні лапок (під тильдой ~ на клавіатурі).) Це буде відправляти вихід command1в command2якості аргументів командного рядка. Зауважте, що імена файлів, що містять пробіли (нові рядки тощо), будуть розбиті на окремі аргументи.


2
кіт find -name '*.foo' -printпрацював для мене чудово ... Спасибі
Деванг Камдар

Зворотні котирування спрацьовують чудово і є більш узагальненими, ви також можете скористатись цим для перегляду списку файлів із файлу.
Hazok

11
Зауважте, що сучасні версії findдозволяють писати:, find . -name '*.foo' -exec cat {} +де +вказано, що findслід групувати стільки імен файлів, скільки зручно, в одне виклик команди. Це дуже корисно (воно стосується пробілів тощо у назвах файлів, не вдаючись до -print0та xargs -0).
Джонатан Леффлер

18
Невідомо:find . -name '*.foo' | xargs cat
тушковане м'ясо

3
Просто додати відповідь на @stewSquared: Щоб знайти всі рядки у файлах, що містять певний рядок, виконайте цеfind . -name '*.foo' | xargs cat | grep string
Bim

84

Сучасна версія

POSIX 2008 додав +маркер, findщо означає, що він тепер автоматично групує стільки файлів, скільки розумних, в одне виконання команди, як xargsі у нас, але має ряд переваг:

  1. Вам не доведеться турбуватися про непарні символи в іменах файлів.
  2. Вам не доведеться турбуватися про те, що команда викликається нульовими іменами файлів.

Проблема з іменем файлу - це проблема, яка xargsне має -0можливості, і проблема "запустити навіть з нульовими іменами файлів" є проблемою з -0варіантом або без нього, але GNU xargsмає -rабо --no-run-if-emptyможливість запобігти цьому. Крім того, це позначення скорочує кількість процесів, а не те, що ви, ймовірно, вимірюєте різницю в продуктивності. Отже, ви могли б розумно написати:

find . -exec grep something {} +

Класична версія

find . -print | xargs grep something

Якщо ви працюєте в Linux або маєте команду GNU findта xargsкоманди, тоді використовуйте за -print0допомогою findі -0з xargsдля обробки імен файлів, що містять пробіли та інші символи непарних кульок.

find . -print0 | xargs -0 grep something

Налаштування результатів від grep

Якщо ви не хочете, щоб імена файлів (лише текст), тоді додайте відповідний параметр grep(як правило, -hдля придушення "заголовків"). Щоб абсолютно гарантувати, що ім'я файлу друкується grep(навіть якщо знайдено лише один файл, або останній виклик grepмає лише 1 ім’я файлу), тоді додайте /dev/nullдо xargsкомандного рядка, щоб завжди було принаймні два імені файлів.


Для заплутаних, як я, зауважте, що цей спосіб спочатку дасть усі результати пошуку, а потім дасть вихід xargs grep something.
Ерік Ху

3
@EricHu: Я можу бачити, що ви розгублені, але це не так, як ви говорите, це робить, принаймні, не в будь-якій системі Unix, про яку я знаю. Вихідні дані findпрокладаються на стандартний вхід xargs. xargsПрограма зчитує стандартний ввід, розділяючи вхід в порожній простір (прогалини, нові рядки, вкладки і т.д.) і додає число слів в команду grep somethingі виконує командний рядок. xargsпотім продовжує зчитування введення та виконання команд, поки не закінчиться введення. xargsзапускає grepкоманду стільки разів, скільки потрібно для введення, яке їй дано (з findцього прикладу).
Джонатан Леффлер

Ну моя помилка, це використання grep для пошуку в кожному зібраному файлі. Я шукав, щоб просто відфільтрувати вихід знахідки грепом
Ерік Ху

1
Помилки переходять до стандартної помилки (дескриптор файлу 2) у всіх добре сприйнятих командах. Перенаправлення stderr, щоб /dev/nullвтратити повідомлення про помилки.
Джонатан Леффлер

1
Це також має перевагу в тому, що вона краще працює з пробілами у шляху до файлів. Навіть "sed'ing" "->" \ "розбиває його з` але з xargs, він прекрасно працює
JZL003

36

Існує декілька способів передати список команд, повернених findкомандою, catкоманді, хоча технічно не всі використовують трубопроводи, і жоден насправді не передає безпосередньо cat.

  1. Найпростішим є використання зворотних посилань ( `):

    cat `find [whatever]`
    

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

  2. У деяких оболонках, в тому числі bash, можна використовувати $()замість задньої панелі:

    cat $(find [whatever])
    

    Це менш портативно, але нестабільно. Крім цього, він має майже ті самі застереження, що і бекстейки.

  3. Оскільки виконання інших команд над тим, що було знайдено, є загальним для використання find, функція find має -execдію, яка виконує команду для кожного знайденого файла:

    find [whatever] -exec cat {} \;
    

    Це {}заповнювач імені файлу і \;позначає кінець команди (Можливо, після цього можна виконати інші дії -exec.)

    Це запускається catодин раз для кожного окремого файлу, а не запускає один екземпляр catпередачі йому декількох імен файлів, що може бути неефективним і не може мати поведінку, яку ви хочете для деяких команд (хоча це добре для cat). Синтаксис також незручний для набору - вам потрібно уникнути крапки з комою, оскільки крапка з комою є особливою для оболонки!

  4. Деякі версії find( в першу чергу в версії GNU) дозволяють замінити ;з +для використання -exec« в режимі S дописування для запуску менше випадків cat:

    find [whatever] -exec cat {} +
    

    Це передасть кілька імен файлів до кожного виклику cat, що може бути більш ефективним.

    Зауважте, що для цього не гарантується використання одного виклику. Якщо командний рядок буде занадто довгим, аргументи поширюються на кілька викликів cat. Бо catце, мабуть, не велика справа, але для деяких інших команд це може змінити поведінку небажаними способами. У системах Linux обмеження довжини командного рядка досить велике, тому поділ на кілька викликів є досить рідкісним порівняно з деякими іншими ОС.

  5. Класичним / портативним підходом є використання xargs:

    find [whatever] | xargs cat
    

    xargsзапускає вказану команду ( catу цьому випадку) та додає аргументи на основі того, що вона читає з stdin. Так само, як і -execз +цим, це порушить командний рядок, якщо це необхідно. Тобто, якщо findвиробляється занадто багато результату, він запускатиметься catкілька разів. Як було сказано в розділі про -execраніше, є деякі команди, де це розщеплення може спричинити різну поведінку. Зауважте, що при такому використанні xargsвиникають проблеми з пробілами у назви файлів, оскільки xargsпросто використовується пробіл як роздільник.

  6. Найбільш надійний, портативний та ефективний метод також використовує xargs:

    find [whatever] -print0 | xargs -0 cat
    

    -print0Прапор вказує findвикористовувати \0(нульовий символ) роздільники між іменами файлів і -0прапор вказує xargsочікувати ці \0роздільники. Ця поведінка має майже однакову поведінку з -exec... +підходом, хоча і більш портативною (але, на жаль, більш багатослівною).


Метод backtick чудовий, тому що він працює і для інших команд, таких як ls.
Мартін Браун

@Martin Braun за допомогою $()Також працює з іншими командами find .
Лоранс Гонсалвс

Дякую, добре знати, я якось перестав читати після (1), тому що це відповідає моїм потребам, оскільки я не маю справу з особливими символами, такими як пробіли та подібні.
Мартін Браун

9

Для досягнення цього (використовуючи bash) я би зробив наступне:

cat $(find . -name '*.foo')

Це відоме як "заміна команди", і воно знімає подачу рядків за замовчуванням, що дійсно зручно!

більше інформації тут


6

Мені звучить робота для сценарію оболонки:

for file in 'find -name *.xml'
do
   grep 'hello' file
done

чи щось подібне


2
Це дійсна, хоча і не обов'язково оптимальна відповідь на питання.
Джонатан Леффлер

1
... так, але це чудово, якщо ви хочете, щоб і один великий файл із назвами файлів перерахований.
ʍǝɥʇɐɯ

1
Мені це подобається найкраще. Блок-шлейф, як цей, залишає можливість робити інші речі.
kakyo

4

Ось мій спосіб знайти імена файлів, які містять деякий вміст, який мене цікавить, лише один рядок bash, який також добре обробляє пробіли у назви файлів:

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done

3

Я використовую щось подібне:

find . -name <filename> -print0 | xargs -0 cat | grep <word2search4>

« -print0» Аргумент «знайти» і « -0» аргумент «xargs» необхідні для рукоятки пробілу в дорозі до файлів / імена правильно.



2

Ось мій знімок для загального використання:

grep YOURSTRING `find .`

Він надрукує ім'я файлу


2

В bash, було б доречним наступне:

find /dir -type f -print0 | xargs -0i cat {} | grep whatever

Тут ви знайдете всі файли в /dirкаталозі та безпечно вкажіть назви файлів у файли, в xargsякі безпечно працюватимуть grep.

Пропуск xargsне є хорошою ідеєю, якщо у вас багато тисяч файлів /dir; catзламається через надмірну довжину списку аргументів. xargsрозберемо це все для вас.

-print0Аргумент findсіток з -0аргументом xargsдля обробки імен файлів з пробілами правильно. -iАргумент xargsдозволяє вставити ім'я файлу , де це необхідно в catкомандному рядку. Дужки замінюються назвою файлу, переданого в catкоманду з find.



0

Використовуйте ggrep .

ggrep -H -R -I "mysearchstring" *

для пошуку файлу в unix, що містить текст, що знаходиться в поточному каталозі або підкаталозі


0

Це надрукує ім'я та вміст файлів лише рекурсивно.

find . -type f -printf '\n\n%p:\n' -exec cat {} \;

Редагувати (вдосконалена версія): Це надрукує назву та вміст текстових файлів (ascii) лише рекурсивно.

find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'

Ще одна спроба

find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;

-1

Ви намагаєтесь знайти текст у файлах? Ви можете просто використовувати grep для цього ...

grep searchterm *

-1

Список та перегляд вмісту всіх файлів abc.def на сервері в каталогах / ghi та / jkl

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;

Щоб перелічити abc.def файли, котрі коментують записи та відображають, див. Ці записи в каталогах / ghi та / jkl

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.