-2

I've been searching for a long time and can't find an answer that works. I have a list with partial filenames (the first few letters of the filenames). If I place the file names individually as follows it works:

find ~/directory/to/search -name "filename*" -print -exec cp '{}' ~/directory/to/copyto \;

If I try to include the list in this scenario it does not:

cat ~/directory/List.txt | while read line 
do 
echo "Text read from file - $line" 
find ~/directory/to/search -name "$line*" -type f
done

neither does this:

cat ~/directory/List.txt | while read line 
do 
echo "Text read from file - $line" 
find ~/directory/to/search -name "$line&*" -type f
done

Ultimately, I'd like to add:

-exec cp '{}' ~/directory/to/copy/to \;

And copy over all files matching the find criteria.

I've tried using grep but the files are huge so it would take forever. I tried using all sorts of combinations of find, xargs, cp, grep and regex as read in previous searches and no luck.

Is the only solution to write a long script with a bunch of if then statements? I've been using Linux but it would be cool to use it on mac as well.

Cyrus
  • 84,225
  • 14
  • 89
  • 153
RLz
  • 1
  • 1
  • 1
    What's the output of your attempts, and what are the filenames you're looking for? – Benjamin W. Aug 15 '18 at 05:39
  • 1
    I can't replicate this. `while read name; do find . -name "$name*"; done << – Jon Aug 15 '18 at 08:43
  • "it doesn't work" is the worst possible problem description. "Hey mechanic my car doesn't work - here's a photo of it, now tell me what's wrong with it". Tell us in what way it "doesn't work" - wrong output, no output, error messages, core dumps, something else? – Ed Morton Aug 15 '18 at 12:26
  • @Jon it seems what you tried is similar to my first attempt above.I tried using: `while read line; do find . -name "$line&*" \; ; done < ~/data/Studies/EST/ESTlist.txt` but came across a: `find: paths must precede expression:` error. – RLz Aug 15 '18 at 20:08
  • @RLz Ah, that is because of the `\;`, which isn't needed (it is the terminator for the `-exec` option). Take that out and you might be good. Also, should that `$line&*` just be `$line*`? The `&` isn't needed to concatenate in Bash. – Jon Aug 16 '18 at 08:14
  • @Jon I tried `while read line; do echo "Looking for $line"; find ~/data/Raw -name "$line*" ; < cat ~/data/Studies/EST/ESTlist.txt \; ; done` both with and without the & and while it does read the file as evident by echo it does not return the find results. – RLz Aug 16 '18 at 16:33

1 Answers1

0

Here is a crude attempt at getting away with a single find invocation.

predicates=()
or=''
while read -r line; do
    predicates+=($or -name "$line*")
    or="-o"
done < ~/directory/list.txt
find ~/directory/to/search -type f \( "${predicates[@]}" \) \
    -exec cp -t ~/directory/to/copy/to {} + 

The array functionality requires an extended shell (Bash, ksh, etc) with this functionality; it won't work with /bin/sh.

cp -t is a GNU extension; if you don't have that, maybe just use your original -exec cp {} dir \; though it will be less efficient. Some old versions of find also don't support -exec ... +.

tripleee
  • 175,061
  • 34
  • 275
  • 318