zpoint
zpoint

Reputation: 121

terminal - combining find with xargs - find on the right side

There is a file in plain text named keywords.txt,

For every WORD in keywords.txt, I want to find all the filename in current directory containing that WORD

cat keywords.txt | xargs find . -name

Error in Mac:

find: xxx: unknown primary or operator

Error in Ubuntu:

find: paths must precede expression: xxx
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec|time] [path...] [expression]

Question:

  1. It would be great if you can tell me why the error occurs, How to fix it?
  2. I want to pass the pattern to find so that I can find every filename containing WORD, how to do that?

    cat keywords.txt | xargs find . -name {*WORD*}
    

I searched google, most of the use cases:

find on left and xargs on right side, not the answer I expect.

Upvotes: 0

Views: 203

Answers (1)

Kusalananda
Kusalananda

Reputation: 15613

The error occurs since xargs adds more than one word to the end of the given command, resulting in a find invocation that may look like

find . -name string1 string2 string3 etc.

The following short shell script will find all files (regardless of type) that contains any of the strings given on its command line anywhere in their filenames:

#!/bin/sh

# construct options for 'find' that matches filenames using multiple
# -o -name "*string*"
for string do
    set -- "$@" -o -name "*$string*"
    shift
done

# there's a -o too many at the start of $@ now, remove it
shift

# add e.g. -type f to only look for regular files
find . '(' "$@" ')'

You may call this from xargs:

xargs -n 100 ./script.sh <keywords.txt

Since the script calls find with an expanded command line, I have restricted the number of allowed strings to call the script with to 100 to be on the safe side.

Note that this will split strings in keywords.txt that contain spaces.

Upvotes: 1

Related Questions