What would be the best way to create a list of files that have common words with a given file. For example, if I had:

$ ls
  mainFile  file1  file2  file file4
$ cat mainFile
  exquisite malicious sentient pulsating
  perspicacious one
  tawdry fumigate Baryshnikov O'connor

and I wanted to list any of the files in the cwd that contained any one of the words in mainFile. What would be the best way to go about this?

Since the number of words per line in mainFile is not constant, I was finding solutions using cut a little tricky. I was trying to create a string out of the words and then place them separated by | in a grep -l "exquisite|malicious|etc" * command. I'm open to any method though that might be better.


First generate indices for mainFile,

sed 's/ /\n/g' mainFile | sort | uniq > mainFile.idx

Then do a grep for fixed strings:

grep -F -f mainFile.idx file*

  • This is great. I am extracting the base file name with the following: sed 's/:.*//' | sed 's/.*\///'; is this a good way to do it? I couldn't seem to find a switch that would just output base filename. – stariz77 Nov 4 '12 at 11:02
  • @stariz77 not sure if I get your script, but to get the base name, use basename /path/to/file – daisy Nov 4 '12 at 11:38
  • you understood it fine. Just the output from your command is /path/to/file/file1:tawdry malicious, i.e., path and list of words found. I just want the filename (basename) and no list of found words. I thought maybe there was a way to to specify this output with your solution or something. – stariz77 Nov 4 '12 at 11:45
  • @stariz77 I seems to get it, to retrieve the file name in that situation, use awk -F ':' { print $1 } – daisy Nov 5 '12 at 4:19
  • or use the -l option to grep. Also, it's not going to match words. So if for instance mainfile contains "one", it will match all files that contain "gone", "honey"... See the "-w" option for that. Also note that \n in the RHS of sed's s command is not standard (you can use tr instead). Also note that you don't need the temporary file, you can use -f <(...) or pass the list of words on the command line. – Stéphane Chazelas Nov 5 '12 at 10:57

If your grep supports the non-standard -w option (for matching words):

grep -lwFe "$(tr -cs "[[:alnum:]_'-]" '[\n*]' < mainfile | sort -u)" file*

use this code:

    for pattern in `cat mainfile`
    grep -l "$pattern" file*


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.