Трубопровод из находки в grep

8

Что я пытаюсь сделать?

Напишите команду, которая ищет любые файлы, которые не требуются для других файлов в моем проекте.

Что я пробовал?

Я использую, findчтобы получить список имен файлов. Теперь я хочу использовать имена файлов в качестве строки поиска (а не файл для поиска).

Я использую, find server/lib -type f -exec basename {} \; | cut -f 1 -d '.'чтобы получить свой список имен файлов и удаляю расширение файла.

Теперь я знаю, что это grep -R --exclude-dir=node_modules <search-string> . -lто, к чему я хочу передать каждое имя файла, но я не знаю, как передать их в качестве <search-string>аргумента.


Дополнительная информация

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

Кроме того (хотя это, вероятно, не входит в сферу действия этого вопроса), поскольку я использую это как способ найти любое из имен файлов, grepдля которых ничего не удается найти, любой совет по получению такого рода вывода будет принят с благодарностью

> <the-command>

filename1
server/lib/foo.js # where these are the list of files in which it appears
test/lib/foo.js

filename2
Not Found! #where `filename2` wasn't found anywhere (obviously)
Саймон Легг
источник

Ответы:

2

Короткий ответ:

Если вы просто хотите передать несколько строк в качестве аргументов другой команде, xargsэто ваш друг - в данном случае, потому что вы помещаете ее в середину команды, вы захотите использовать -I {}флаг. Это устанавливает {}в качестве заполнителя, так что вы можете поместить куда угодно (вы можете установить свой собственный заполнитель, но я обычно придерживаюсь, {}так как он не будет принят за многие другие вещи.

Собираем все вместе (при условии, что команды, которые вы дали, делают то, что вы думаете!):

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} grep -R --exclude-dir=node_modules {} . -l

Длинный ответ

Хорошо, так что мы, вероятно, можем пойти дальше. Допустим, вы хотите формат , который вы упомянули ранее - вы можете xargsв sh -cтак что вы можете команды цепи:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l"

Запуск этого на моей машине, она выглядит , как это дает вам файлы , где файл будет найден. Мой мозг устал, поэтому вместо того, чтобы обернуть его в хороший скрипт (именно это вы должны делать, когда oneliners начинают становиться скучным, и использовать https://www.shellcheck.net/, пока вы в нем), вы можете вместо этого используйте этот ужасный хак, который (я думаю) даст вам результат, который вы ищете:

find server/lib -type f -exec basename {} \; | cut -f 1 -d '.' | xargs -I {} sh -c "echo {}; grep -R --exclude-dir=node_modules {} . -l && printf \"\n\" || printf \"Not found\n\n\""

колос
источник
Большое спасибо, да, xargs -I {}это то, что я искал.
Саймон Легг
6

С zsh:

projects=(server/lib/**/*(D.:t:r))
grep -rFl --exclude-dir=node_modules -e${(u)^projects} .
  • **/рекурсивное сглаживание. Функция, представленная zshв начале 90-х годов.
  • (D.:t:r)является ограничителем глобуса, zshспецифической функцией, которая позволяет выбирать файлы, используя атрибуты, отличные от имени, или изменять сортировку или вносить изменения в найденные файлы.
  • D: включить точечные файлы и перемещать точечные каталоги, как если findбы Скорее всего, вы хотели бы снять это.
  • .: только обычные файлы (как -type fв find)
  • :t, :r: модификаторы истории, как в csh/, bashно здесь применяются к файлам globbed. :tдля хвоста (базовое имя), :rдля корневого имени (расширение удалено).
  • x${^array}распределяет элементы как rc's x^$arrayили fish' s x$array. Например, если $arrayесть ( 1, 2). Это становится x1 x2.
  • ${(u)array}(для unique), удалите дубликаты ( (u)являющиеся флагом расширения параметра).

Для списка файлов , которые не содержат ни один из строк, заменить -lс -L(при условии , GNU grep, но вы уже используете опции GNU-конкретных здесь). -Fпредназначен для поиска по фиксированным строкам (поскольку вы, вероятно, не хотите, чтобы эти имена проектов рассматривались как регулярные выражения). Вы также можете добавить -wопцию grepдля совпадения слов, чтобы fooона не совпадала, foobarнапример ( foo-barхотя все равно будет соответствовать ).

Стефан Шазелас
источник
Огромное спасибо за это и за объяснения, я не знал о projects=(server/lib/**/*(D.:t:r))создании такого массива в zsh. Однако теперь мне нужно перечислить файлы, где grepничего не удалось найти. Я думаю, мне нужно было бы поймать 0 / ложный код выхода?
Саймон Легг
@ Симон, см. Часть -Lв конце ответа
Стефан
Да, я видел это. -lговорит мне, где был результат поиска и -Lговорит мне, где он не был найден. Но я хочу знать список поисковых терминов , которые нигде не были найдены, а не где они были / не были найдены
Саймон Легг