Как использовать grep для всех файлов нерекурсивно в каталоге?

Я хочу выполнить поиск строки текста во всех файлах в каталоге (а не в его подкаталогах; я знаю, что -r опция делает это, но это не то, чего я хочу).

  1. Бегущий

    grep "string" /path/to/dir

    предполагается, что я могу это сделать, я читал, но это выдает мне ошибку:

    grep: dir: Это каталог

  2. Затем я попробовал запустить grep на нескольких файлах.

    grep "string" .bashrc .bash_aliases работает отлично.

    grep "string" .bash* тоже работает по назначению.

    grep "string" * выдает мне ошибки:

    grep: data: Is a directorygrep: Desktop: Is a directorygrep: Documents: Is a directorygrep: Downloads: Is a directory...

Печатаются только ошибки, я не получаю совпадающих строк. Я попытался использовать -s вариант, но безрезультатно.

Итак, мои вопросы:

  1. Почему я не могу использовать grep в каталоге, как в (1), когда я должен быть в состоянии? Я видел, как это делается во множестве примеров в Интернете.
    Редактировать: Когда я говорю "использование grep в каталоге", я имею в виду "поиск по всем файлам в этом каталоге, исключая его подкаталоги". Я полагаю, что это то, что делает grep, когда вы передаете ему каталог вместо файла. Я ошибаюсь?

  2. Пожалуйста, дайте мне объяснение того, как работает grep это объяснило бы поведение команд в (2).
    Редактировать: Позвольте мне быть более конкретным. Почему использование подстановочных знаков для указания нескольких файлов для поиска для работы с .bash* и не с * или даже ./*?

  3. Как я могу выполнить поиск по всем файлам в каталоге (а не в его подкаталогах) с помощью grep?

В Bash глобус не будет расширяться в скрытые файлы, поэтому, если вы хотите выполнить поиск все файлы в каталоге, вам нужно указать скрытые файлы .* и не скрытый *.

Чтобы избежать ошибок "Это каталог", вы могли бы использовать -d skip, но в моей системе я также получаю сообщение об ошибке grep: .gvfs: Permission denied, поэтому я предлагаю использовать -s, который скрывает все сообщения об ошибках.

Итак, команда, которую вы ищете, - это:

grep -s "string" * .*

Если вы ищете файлы в другом каталоге:

grep -s "string" /path/to/dir/{*,.*}

Другим вариантом является использование dotglob опция оболочки, которая заставит глобус включать скрытые файлы.

shopt -s dotglobgrep -s "string" *

Для файлов в другом каталоге:

grep -s "string" /path/to/dir/*

† Кто-то упомянул, что я не должен получать эту ошибку. Возможно, они правы - я кое-что прочитал, но сам ничего не понял.

Вам нужен -d skip опция добавлена.

  1. Grep выполняет поиск внутри файлов. Вы можете выполнять рекурсивный поиск, как вы сказали, если хотите искать файлы внутри каталога.

  2. По умолчанию grep считывает все файлы и определяет каталоги. Поскольку по умолчанию вы не определили, что делать с каталогами с -d опция, она выдает вывод с ошибкой.

  3. Поиск только в родительском каталоге будет grep -d skip "string" ./*

Старожилы, вероятно, сделали бы это:

find . -type f -print0 | xargs -0 grep "string"

Вы можете думать так, например, используя grep.

grep -l PATH ~/.[^.]*

Таким образом, этот поиск по строке "ПУТЬ" со списком имен файлов под домашним каталогом пользователя выполняется только для файлов, начинающихся с точки.

/root/.bash_history/root/.bash_profilegrep: /root/.cache: Is a directorygrep: /root/.config: Is a directorygrep: /root/.dbus: Is a directory

Используя grep PATH ~/.[^.]* вы увидите все вхождения, включая строку с ключевым словом для поиска.

/root/.bash_history:echo $PATH/root/.bash_history:echo $PATH/root/.bash_history:PATH=$PATH:~/bin/root/.bash_history:echo $PATH/root/.bash_profile:PATH=$PATH:$HOME/bin/root/.bash_profile:export PATHgrep: /root/.cache: Is a directorygrep: /root/.config: Is a directorygrep: /root/.dbus: Is a directory

Чтобы избавиться от перенаправления ошибки в /dev/null, например

grep PATH ~/.[^.]* 2>/dev/null/root/.bash_history:echo $PATH/root/.bash_history:echo $PATH/root/.bash_history:PATH=$PATH:~/bin/root/.bash_history:echo $PATH/root/.bash_profile:PATH=$PATH:$HOME/bin/root/.bash_profile:export PATH

Таким образом, вы можете применить этот шаблон для поиска строки "Apache" в файлах из каталога /etc - поиск только в файлах ниже этого основного каталога. Вы видите, что это не возвращается из /etc/httpd/conf/httpd.conf

grep Apache /etc/[^.]* 2>/dev/null/etc/passwd:apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin/etc/services:derby-repli     4851/tcp                # Apache Derby Replication/etc/services:derby-repli     4851/udp                # Apache Derby Replication

Перефразируя - вы хотите использовать grep для файлов на одном уровне подкаталога, но не выполнять рекурсию по всем подкаталогам?

grep forthis  *  */*

Или если вы не хотите, чтобы файлы находились в текущем каталоге

grep forthis  */*

Обратите внимание, что при этом не будут найдены каталоги, начинающиеся с точки.

grep forthis  .*/*    */*   

должен выполнять эту работу.

Там также есть -maxdepth и -mindepth параметры ограничения, доступные для find командование тоже.

Вот пример правильного пропуска каталогов без скрытия всех ошибок (без -s параметр по выбранному ответу):

grep --directories='skip' 'searchString' *

Кроме того, вы полагаетесь на расширяющиеся подстановочные знаки оболочки, такие как “*”, известные как глобализация. Глобализация не включает имена файлов, начинающиеся с точки, такие как .bashrc в качестве стандарта. Вы можете настроить параметры оболочки так, чтобы она включала эти файлы, но вы можете попасть в небольшую передрягу, если не знаете, что делаете. Хорошее руководство по пониманию глобализации можно найти здесь http://mywiki .wooledge.org/glob

Я не знаю почему, но я всегда делал глобализацию скрытых файлов, и это всегда срабатывало. Я не менял никаких настроек или что-то в этом роде. Как я указывал в (2), он также работает с grep "string" .bash*.

Также это linux - How do I use grep to search the current directory for all files having the a string "hello" yet display only .h and .cc files? - Stack Overflow

Извините, мой последний пример был неверным. Вы также можете выполнять поиск в скрытых файлах и подавлять “это каталог”, потому что Linux технически рассматривает каталоги как файлы другого типа. Тогда команда будет следующей: grep "string" * .* 2>/dev/null или grep -s "string" * .*