JavaEar 专注于收集分享传播有价值的技术资料

如何在Linux上找到包含特定文本的所有文件? (How do I find all files containing specific text on Linux?)

问题描述


英文原文

I'm trying to find a way to scan my entire Linux system for all files containing a specific string of text. Just to clarify, I'm looking for text within the file, not in the file name.

When I was looking up how to do this, I came across this solution twice:

find / -type f -exec grep -H 'text-to-find-here' {} \;

However, it doesn't work. It seems to display every single file in the system.

Is this close to the proper way to do it? If not, how should I? This ability to find text strings in files would be extraordinarily useful for some programming projects I'm doing.


中文翻译

我正试图找到一种方法来扫描整个Linux系统,查找包含特定文本字符串的所有文件。只是为了澄清,我正在寻找文件中的文本,而不是文件名。

当我查找如何执行此操作时,我遇到了两次此解决方案:

  find / -type f -exec grep -H'text-to-find-here'{} \;
 

然而,它不起作用。它似乎显示系统中的每个文件。

这是否接近正确的方法?如果没有,我该怎么办?这种在文件中查找文本字符串的能力对于我正在进行的一些编程项目非常有用。

I'm trying to find a way to scan my entire Linux system for all files containing a specific string of text. Just to clarify, I'm looking for text within the file, not in the file name.

When I was looking up how to do this, I came across this solution twice:

find / -type f -exec grep -H 'text-to-find-here' {} \;

However, it doesn't work. It seems to display every single file in the system.

Is this close to the proper way to do it? If not, how should I? This ability to find text strings in files would be extraordinarily useful for some programming projects I'm doing.

我正试图找到一种方法来扫描整个Linux系统,查找包含特定文本字符串的所有文件。只是为了澄清,我正在寻找文件中的文本,而不是文件名。

当我查找如何执行此操作时,我遇到了两次此解决方案:

  find / -type f -exec grep -H'text-to-find-here'{} \;
 

然而,它不起作用。它似乎显示系统中的每个文件。

这是否接近正确的方法?如果没有,我该怎么办?这种在文件中查找文本字符串的能力对于我正在进行的一些编程项目非常有用。

37个回答

    最佳答案
  1. You can use:

    grep -r "string to be searched"  /path/to/dir
    

    The r stands for recursive and so will search in the path specified and also its sub-directories. This will tell you the file name as well as print out the line in the file where the string appears.

    Or a command similar to the one you are trying (example: ) for searching in all javascript files (*.js):

    find . -name '*.js' -exec grep -i 'string to search for' {} \; -print
    

    This will print the lines in the files where the text appears, but it does not print the file name.

  2. 参考答案2
  3. find /path -type f -exec grep -l "string" {} \;
    

    Explanation from comments

    find is a command that lets you find files and other objects like directories and links in subdirectories of a given path. If you don't specify a mask that filesnames should meet, it enumerates all directory objects.

    -type f specifies that it should proceed only files, not directories etc.
    -exec grep specifies that for every found file, it should run grep command, passing its filename as an argument to it, by replacing {} with the filename
    
  4. 参考答案3
  5. Hope this is of assistance...

    Expanding the grep a bit to give more information in the output, for example, to get the line number in the file where the text is can be done as follows:

    find . -type f -name "*.*" -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searthtext"
    

    And if you have an idea what the file type is you can narrow your search down by specifying file type extensions to search for, in this case .pas OR .dfm files:

    find . -type f \( -name "*.pas" -o -name "*.dfm" \) -print0 | xargs --null grep --with-filename --line-number --no-messages --color --ignore-case "searchtext"
    

    Short explanation of the options:

    1. . in the find specifies from the current directory.
    2. -name "*.*" : for all files ( -name "*.pas" -o -name "*.dfm" ) : Only the *.pas OR *.dfm files, OR specified with -o
    3. -type f specifies that you are looking for files
    4. -print0 and --null on the other side of the | (pipe) are the crucial ones, passing the filename from the find to the grep embedded in the xargs, allowing for the passing of filenames WITH spaces in the filenames, allowing grep to treat the path and filename as one string, and not break it up on each space.
  6. 参考答案4
  7. You can use grep -ilR:

    grep -Ril "text-to-find-here" /
    
    • i stands for ignore case (optional in your case).
    • R stands for recursive.
    • l stands for "show the file name, not the result itself".
    • / stands for starting at the root of your machine.
  8. 参考答案5
  9. A Simple find can work handy. alias it in your ~/.bashrc file:

    alias ffind find / -type f | xargs grep
    

    Start a new terminal and issue:

    ffind 'text-to-find-here'
    
  10. 参考答案6
  11. I wrote a Python script which does something similar. This is how one should use this script.

    ./sniff.py path pattern_to_search [file_pattern]
    

    The first argument, path, is the directory in which we will search recursively. The second argument, pattern_to_search, is a regular expression which we want to search in a file. We use the regular expression format defined in the Python re library. In this script, the . also matches newline.

    The third argument, file_pattern, is optional. This is another regular expression which works on a filename. Only those files which matches this regular expression will be considered.

    For example, if I want to search Python files with the extension py containing Pool( followed by word Adaptor, I do the following,

    ./sniff.py . "Pool(.*?Adaptor"  .*py
    ./Demos/snippets/cubeMeshSigNeur.py:146 
    ./Demos/snippets/testSigNeur.py:259 
    ./python/moose/multiscale/core/mumbl.py:206 
    ./Demos/snippets/multiComptSigNeur.py:268 
    

    And voila, it generates the path of matched files and line number at which the match was found. If more than one match was found, then each line number will be appended to the filename.

  12. 参考答案7
  13. You can use this:

    grep -inr "Text" folder/to/be/searched/
    
  14. 参考答案8
  15. The below command will work fine for this approach:

    find ./ -name "file_pattern_name"  -exec grep -r "pattern" {} \;
    
  16. 参考答案9
  17. Use:

    grep -c Your_Pattern *
    

    This will report how many copies of your pattern are there in each of the files in the current directory.

  18. 参考答案10
  19. Do the following:

    grep -rnw '/path/to/somewhere/' -e 'pattern'
    
    • -r or -R is recursive,
    • -n is line number, and
    • -w stands for match the whole word.
    • -l (lower-case L) can be added to just give the file name of matching files.

    Along with these, --exclude, --include, --exclude-dir or --include-dir flags could be used for efficient searching:

    • This will only search through those files which have .c or .h extensions:

      grep --include=\*.{c,h} -rnw '/path/to/somewhere/' -e "pattern"
      
    • This will exclude searching all the files ending with .o extension:

    grep --exclude=*.o -rnw '/path/to/somewhere/' -e "pattern"
    
    • Just like exclude files, it's possible to exclude/include directories through --exclude-dir and --include-dir parameter. For example, this will exclude the dirs dir1/, dir2/ and all of them matching *.dst/:
    grep --exclude-dir={dir1,dir2,*.dst} -rnw '/path/to/somewhere/' -e "pattern"
    

    This works very well for me, to achieve almost the same purpose like yours.

    For more options check man grep.

  20. 参考答案11
  21. To search for the string and output just that line with the search string:

    for i in $(find /path/of/target/directory -type f); do grep -i "the string to look for" "$i"; done
    

    e.g.:

    for i in $(find /usr/share/applications -type f); \
    do grep -i "web browser" "$i"; done
    

    To display filename containing the search string:

    for i in $(find /path/of/target/directory -type f); do if grep -i "the string to look for" "$i" > /dev/null; then echo "$i"; fi; done;
    

    e.g.:

    for i in $(find /usr/share/applications -type f); \
    do if grep -i "web browser" "$i" > /dev/null; then echo "$i"; \
    fi; done;
    
  22. 参考答案12
  23. Silver Searcher is a terrific tool, but ripgrep may be even better.

    It works on Linux, Mac and Windows, and was written up on Hacker News a couple of months ago (this has a link to Andrew Gallant's Blog which has a GitHub link):

    Ripgrep – A new command line search tool

  24. 参考答案13
  25. Try this:

    find . | xargs grep 'word' -sl
    
  26. 参考答案14
  27. If you have a set of files that you will always be checking you can alias their paths, for example:

    alias fd='find . -type f -regex ".*\.\(inc\|info\|module\|php\|test\|install\|uninstall\)"'
    

    Then you can simply filter the list like this:

    grep -U -l $'\015' $(fd)
    

    Which filters out the list fd to files that contain the CR pattern.

    I find that aliasing the files that I am interested in helps me create easier scripts then always trying to remember how to get all those files. The recursive stuff works as well but sooner or later you are going to have to contend with weeding out specific file types. Which is is why I just find all the file types I'm interested in to begin with.

  28. 参考答案15
  29. You can use the below command as you don't want a file name, but you want to search from all the files. Here are I am capturing "TEXT" from all the log files, making sure that the file name is not printed:

    # grep -e TEXT *.log | cut -d' ' --complement -s -f1
    

    Using grep with the -e option is quite quick compared to other options as it is for a PATTERN match.

  30. 参考答案16
  31. Avoid the hassle and install ack-grep. It eliminates a lot of permission and quotation issues.

    apt-get install ack-grep
    

    Then go to the directory you want to search and run the command below

    cd /
    ack-grep "find my keyword"
    
  32. 参考答案17
  33. There is an ack tool that would do exactly what you are looking for.

    http://linux.die.net/man/1/ack

    ack -i search_string folder_path/*
    

    You may ignore -i for case sensitive search

  34. 参考答案18
  35. grep -Erni + "text you wanna search"
    

    The command will search recursivly in all files and directories of the current directory and print the result.

    Note: if your grep output isn't colored, you can change it by using the grep='grep --color=always' alias in your shell src file

  36. 参考答案19
  37. All previous answers suggest grep and find. But there is another way: Use midnight commander

    It is a free utility (30 years old, proven by time) which is visual without being GUI. Has tons of functions, finding files is just one of them.

  38. 参考答案20
  39. I am fascinated by how simple grep makes it with 'rl'

    grep -rl 'pattern_to_find' /path/where/to/find
    
    -r to find recursively file / directory inside directories..
    -l to list files matching the 'pattern'
    

    Use '-r' without 'l' to see the file names followed by text in which the pattern is found!

    grep -r 'pattern_to_find' /path/where/to/find
    

    Works just perfect..

    Hope it helps!

  40. 参考答案21
  41. If your grep doesn't support recursive search, you can combine find with xargs:

    find / -type f | xargs grep 'text-to-find-here'
    

    I find this easier to remember than the format for find -exec.

    This will output the filename and the content of the matched line, e.g.

    /home/rob/file:text-to-find-here
    

    Optional flags you may want to add to grep:

    • -i - case insensitive search
    • -l - only output the filename where the match was found
    • -h - only output the line which matched (not the filename)
  42. 参考答案22
  43. Try this

    find . -type f -name some_file_name.xml -exec grep -H PUT_YOUR_STRING_HERE {} \;
    
  44. 参考答案23
  45. I came across this solution twice:

    find / -type f -exec grep -H 'text-to-find-here' {} \;

    (...)

    Is this close to the proper way to do it?

    Short answer: Yes, it is very close.


    Long answer: This command is correct.

    Using just grep -r (grep --recursive) is more straightforward:

    grep 'text-to-find-here' -r <path_to_search>

    However, your command (combining find and grep) comes in handy sometimes, for example on systems where the grep command doesn't support -r (--recursive), so let's examine the rest of the question:

    find / -type f -exec grep -H 'text-to-find-here' {} \;

    (...)

    However, it doesn't work. It seems to display every single file in the system.

    You probably get error messages such as

    grep: '<name_of_file_you_do_have_access_to>': Permission denied
    

    You can avoid these by adding option -s (or --no-messages) to grep.

    But then you still get errors like

    find: '<name_of_file_you_do_have_access_to>': Permission denied
    

    To avoid this, you can add 2>/dev/null at the end of your command, to discard all error messages, which gives:

    find / -type f -exec grep -sH 'text-to-find-here' {} \; 2>/dev/null

  46. 参考答案24
  47. Try this:

    find / -type f -name "*" -exec grep -il "String_to_search" {} \;
    

    Or

    for i in /*;do grep -Ril "String_to_search" $i;done 2> /dev/null
    
  48. 参考答案25
  49. You can use the following commands to find particular text from a file:

    cat file | grep 'abc' | cut -d':' -f2
    
  50. 参考答案26
  51. As Peter in the previous answer mentioned, all previous answers suggest grep and find.

    But there is more sophisticated way using Gnome Commander with perfect GUI and with tons of options since 2001, finding files is just one of them. It is a free utility as well proven by time.

  52. 参考答案27
  53. List of file names containing a given text

    First of all, I believe you have used -H instead of -l. Also you can try adding the text inside quotes followed by {} \.

    find / -type f -exec grep -l "text-to-find-here" {} \; 
    

    Example

    Let's say you are searching for files containing specific text "Apache License" inside your directory. It will display results somewhat similar to below (output will be different based on your directory content).

    bash-4.1$ find . -type f -exec grep -l "Apache License" {} \; 
    ./net/java/jvnet-parent/5/jvnet-parent-5.pom
    ./commons-cli/commons-cli/1.3.1/commons-cli-1.3.1.pom
    ./io/swagger/swagger-project/1.5.10/swagger-project-1.5.10.pom
    ./io/netty/netty-transport/4.1.7.Final/netty-transport-4.1.7.Final.pom
    ./commons-codec/commons-codec/1.9/commons-codec-1.9.pom
    ./commons-io/commons-io/2.4/commons-io-2.4.pom
    bash-4.1$ 
    

    Remove case sensitiveness

    Even if you are not use about the case like "text" vs "TEXT", you can use the -i switch to ignore case. You can read further details here.

    Hope this helps you.

  54. 参考答案28
  55. grep -insr "pattern" *
    
    • i: Ignore case distinctions in both the PATTERN and the input files.
    • n: Prefix each line of output with the 1-based line number within its input file.
    • s: Suppress error messages about nonexistent or unreadable files.
    • r: Read all files under each directory, recursively.
  56. 参考答案29
  57. Try:

    find . -name "*.txt" | xargs grep -i "text_pattern"
    
  58. 参考答案30
  59. grep is your good friend to achieve this.

    grep -r <text_fo_find> <directory>
    

    if you don't care about the case of the text to find then use

    grep -ir <text_to_find> <directory>
    
  60. 参考答案31
  61. Use pwd to search from any directory you are in, recursing downward

    grep -rnw `pwd` -e "pattern"
    

    Update Depending on the version of grep you are using, you can omit pwd. On newer versions . seems to be the default case for grep if no directory is given thus:

    grep -rnw -e "pattern"

    or

    grep -rnw "pattern"

    will do the same thing as above!

  62. 参考答案32
  63. You can use ack. It is like grep for source code. You can scan your entire file system with it.

    Just do:

    ack 'text-to-find-here'
    

    In your root directory.

    You can also use regular expressions, specify the filetype, etc.


    UPDATE

    I just discovered The Silver Searcher, which is like ack but 3-5x faster than it and even ignores patterns from a .gitignore file.

  64. 参考答案33
  65. If you know the extension of your source files (and the project is not too big), use:

    grep "class foo" **/*.c
    

    within the folder of your interest.

    The magic here is by using globbing option (**) which helps you to scan all the files recursively with specific extension. If doesn't work, activate it by shopt -s globstar. You may also use **/*.* for all files (excluding hidden and without extension).

    Add the following useful parameters (most common for source code searching):

    • -i - for insensitive searching,
    • -w - to search for a words (in opposite of partial word matching),
    • -n - for showing the line of your match,
    • --context=5 - to increase context, so you recognise surrounding code better,
    • -color - mark up the matching text with color (sometimes it works by default),
    • -I - to ignore binary files (which by specifying file extension, you actually do).

    If you've the error that your argument is too long, consider narrowing down your search, or use find syntax instead.

  66. 参考答案34
  67. There's a new utility called The Silversearcher

    sudo apt install silversearcher-ag
    

    It works closely with Git and other VCS. So you won't get anything in a .git or another directory.

    You can simply use

    ag -ia "Search query"
    

    And it will do the task for you!

  68. 参考答案35
  69. Here are the several list of commands that can be used to search file.

    grep "text string to search” directory-path
    
    grep [option] "text string to search” directory-path
    
    grep -r "text string to search” directory-path
    
    grep -r -H "text string to search” directory-path
    
    egrep -R "word-1|word-2” directory-path
    
    egrep -w -R "word-1|word-2” directory-path
    
  70. 参考答案36
  71. grep can be used even if we're not looking for a string.

    Simply running,

    grep -RIl "" .
    

    will print out the path to all text files, i.e. those containing only printable characters.

  72. 参考答案37
  73. Try:

    find / -type f -exec grep -H 'text-to-find-here' {} \;
    

    which will search all file systems, because / is the root folder.

    For home folder use:

    find ~/ -type f -exec grep -H 'text-to-find-here' {} \;
    

    For current folder use:

    find ./ -type f -exec grep -H 'text-to-find-here' {} \;