16 Dec 2023
by Zhenke Wu
Share
tweet

1. Quick search on command line?

Want to quickly search in your directories? For example, you want to search for .R files that contain a string "latent", and print out the results. You may hope to do something like:

  • lookfor "latent" ".R"

Or you want to just look for the files without specifying the file type by something like:

  • lookfor "latent"

Or you want to print page-by-page using less

  • lookfor latent | less (the quotation marks around latent are not needed)

If achieved, this could speed up your debugging process when you need to find certain variable names or keywords that you identified as useful.

1.1. Back-story

Here is an excellent solution I have been using (see more explanation at the end):

This was motivated by Rafa Irizarry who was my then-Hopkins professor and taught me 1st year linear regression class running R and compling files in Emacs (I had not been exposed to Unix before PhD):

As you can see by comparing the codes from the two tweets, I have used a different function rg which is faster, but both versions should work.

  • Too many outputs? You may also append "| less" when you use the command, e.g., lookfor latent | less, to print only page-by-page when lookfor identifies exceedingly many files or long files that contain the target string latent. However, by using less, the results lose syntax highlighting. This is why I have no | less by default to make it easier for my eyes when staring at the returned results.

2. Set things up

  • Create the file at /full/path/to/your/file, e.g., I created a file ~/bin/lookfor containing the following bash code:
    • #!/bin/bash
      rg --no-heading -i "$1" --iglob \*$2	
      
  • Make the file excutable:
    • chmod +x /full/path/to/your/file
      
  • Create a symbolic link to the file by following this. The symlink may be in a different location /usr/local/bin/name_of_new_command. I created a symbolic link with the same name (does not have to be), lookfor.
    • sudo ln -s /full/path/to/your/file /usr/local/bin/name_of_new_command
      

2.1. Example

For example, because I created the lookfor file at ~/bin/lookfor, I needed to replace /full/path/to/your/file with ~/bin/lookfor; I wanted to type lookfor to execute the file, so I replaced name_of_new_command with lookfor.

Note that we just created a symbolic in a different directory /usr/local/bin to the now executable file ~/bin/lookfor

Now you may type lookfor with appropriate arguments to do the quick search, save your time, and be less cranky!

3. More explanation (by GPT-4)

#!/bin/bash
rg --no-heading -i "$1" --iglob \*$2	

This Bash script snippet utilizes rg, which is the command for Ripgrep, a fast search tool. The script performs a case-insensitive search for the pattern specified by $1 in files that match the glob pattern *$2.

Here’s a breakdown of the options used:

  • --no-heading: This option tells Ripgrep to omit the file names and just show the matching lines from each file.

  • -i: This flag makes the search case-insensitive, meaning it will match both upper and lower case letters.

  • $1: This is a placeholder for the first argument passed to the script. It represents the search pattern.

  • --iglob \*$2: The --iglob option allows for case-insensitive file name matching. \* matches any number of any characters, and $2 is a placeholder for the second argument to the script, which specifies the file extension or pattern to search within.

Overall, when you run this script with two arguments, it searches for the first argument (a text pattern) in all files that match the pattern given by the second argument (typically a file extension), without regard to case, and outputs the matching lines without file names.


blog comments powered by Disqus