Як я можу зібрати результати FIND за допомогою -EXEC і все-таки вивести файл?


64

Краще пояснити на прикладах.

Я можу:

find . -name "*.py" -type f > output.txt

Але як я можу зберігати вихід у той самий файл для:

find . -name "*.py" -type f -exec grep "something" {} \

Я не можу просто зробити

find . -name "*.py" -type f -exec grep "something" {} \ > output.txt

Відповіді:


105

Якщо я правильно вас зрозумів, це ви хочете зробити:

find . -name '*.py' -print0 | xargs -0 grep 'something' > output.txt

Findвсі файли з розширенням py, grepлише рядки, що містять somethingі зберігають рядки в output.txt. Якщо файл містить що-небудь, його буде замінено.

Редагувати: Використовуючи -exec:

find . -name '*.py' -exec grep 'something' {} \; > output.txt

Я включаю тут коментар Кріс Даунс. Вищевказана команда призведе до grepвиконання стільки разів, скільки findвиявляє виникнення. Однак, якщо ви заміните на ;a +, grepвиклик виводиться з findоб'єднаного (до певної межі). Дивіться питання Використання крапки з комою (;) проти плюс (+) з exec, щоб знайти більше по темі.


16
Використання +замість \;цього значно покращить час виконання (оскільки він буде контактувати з аргументами до виконання до цього часу ARG_MAX).
Кріс Даун

Тепер я розумію силу xargs! Дякую!
domih

4
Використовуйте, grep -Hякщо ви хочете включити ім'я файлу у висновок.
Стейнар

18

Якщо ви хочете зберегти всі відповідні рядки в усіх файлах у output.txt, остання команда спрацьовує, за винятком того, що вам не вистачає потрібної ;в кінці команди.

find . -name "*.py" -type f -exec grep "something" {} \; > output.txt

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

find . -name "*.py" -type f -exec sh -c 'grep "something" <"$0" >"$0.txt"' {} \;

останній справді приємний: D
bakytn

Щоб розширити відповідь на @gilles, щоб зробити її трохи більш інформативною, особливо якщо список файлів, з якими ви маєте справу, великий, ви можете повідомити ім'я файлу (відносний шлях) кожного файлу разом із результатами grep'ed, використовуючи це : find . -name "*.py" -type f -exec grep "something" {} \; -print > output.txt І якщо ви хочете побачити номери рядків з виразними лініями, то, звичайно, можете скористатисяgrep -n "something"
JJMpls

9

Для запису grepє --includeі --excludeаргументи, які можна використовувати для фільтрації файлів, які він шукає:

grep -r --include="*.py" "something" > output.txt

2
Принаймні GNU grepтак.
phk

2

Використання tee:

find . -name '*.py' | tee output.txt | xargs grep 'something'

Протест, якщо у вас є якісь - або файли з допомогою спеціальних символів (включно з пробілами) , що xargsі grepне буде добре працювати ( a file.txtбуде інтерпретуватися як два файли, aа file.txt). Альтернативою тому є використання -xабо -print0, але будь-яке з них забруднить ваше output.txt. -xВикористовуватиме , \щоб уникнути деяких спеціальних символів , і це буде output.txt. -print0Використовуватиме нульові байти в якості роздільника полів (який також вимагає xargs -0) і output.txtбуде виглядати як один довгі безперервні лінії тексту.

Як ви будете мати справу (чи ні) з цим, залежить від вас.

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