I'm trying to get my head around finding files in terminal at the moment. I've found a lot of answers about how to find files to a specific pattern, such as files ending in a certain extension, or from a certain timeframe, etc.
What I've been trying to figure out, though, is how to find and copy multiple arbitrary files, like a list of specific files.
Say, for example, I have the following folders and files
/Documents/Folder_1/
with contents:
file1.txt file2.txt file3.txt file4.txt
/Documents/Folder_2/
with contents:
file5.txt file6.txt file7.txt
/Documents/Folder_3/
with contents:
file8.txt, file9.txt
and what I want to do is to make a new folder called Folder_4
and copy file2.txt
, file5.txt
and file9.txt
to that new folder.
Is there any way to do this through terminal?
What I've tried to do is to make a text list of the file names and call it something like list.txt, e.g.
file2.txt
file5.txt
file9.txt
and loading that text file into the Find command, for example like this:
find /home/usr/Documents -name $cat list.txt
with the thinking that I would then feed the output to either a text list or a copy command, but this doesn't seem to work.
I'm wondering if there is any way to find multiple arbitrary files through the Find command, or am I thinking about this in the wrong way?
EDIT: Just wanted to say thanks for the answers and summarise the way that I ended up approaching this problem. I especially appreciate that someone explained to me that the find command is not designed to accept more than one input without the -o flag, it made me feel a bit less stupid for not being able to figure it out!
What I ended up doing was to make a little shell script and ask for user input and use an array and a for loop to iterate through the list.
Basically the script that I ended up with is more or less like this:
#!/bin/bash
#take user input
echo "Please enter list of filenames to search"
read list
echo "Please enter the folder path to search"
read path
echo "Please enter the destination folder path"
read destination
#use inputted list as input for array, and then use a for loop to find each item on list one by one
array=($list)
for i in "${array[@]}"
do
find "$path" -iname "i" -exec cp '{}' "$destination" \;
done
Best Answer
Unfortunately the
find
command's-name
predicate only accepts a single pattern. If you want to search for multiple files by name you'd need to chain them with the-o
(logicalOR
) operator - something like:This makes it tricky to construct the search programmatically from a list; the closest I can come to your attempted command is:
read the list into a shell array
use the bash shell's
printf
to construct the predicate listuse
eval
to evaluate the resulting command stringThere's a wrinkle here inasmuch as if we use
printf
's format re-use feature to construct the list in this way, we're left with a 'dangling'-o
; we can work around this by terminating the list with a-false
test (since-o -false
is a Boolean no-op) so that our final predicate string becomesPutting it all together - given
and
then
To copy files instead of just listing them, you could then do
resulting in
Note: the
eval
command is powerful and potentially open to abuse: use with care.In practice, given that you appear to want to find only a small number of files, the KISS approach would be to accept the performance hit of multiple
find
calls and just use a loop:or even using
xargs