I have a list of filenames names.list which contains names only. These files are scattered throughout my system in various sub folders but the structure is generally


The constant is spades/filtered

I have used the following command when moving files from one directory

xargs -a file_list.txt cp -t /path/to/dest

And I spotted this thread on using wildcard/ partial file names

find . -path \*content/docs/file.xml

And I tried combining them like so

find . -path \*spades/filtered/ | xargs -a names.list cp -t $HOME/destination/

But I get the following error:

cp: cannot stat `filename': No such file or directory

tldr: I want to copy files using and input list of names only and partial file path


Go through the filenames via a for-loop and append them to the find pattern, copy with exec handle:

for i in $(<names.list)
    find . -path \*spades/filtered/"$i" -type f -exec cp -t "$HOME/destination/" {} \;;

Edit: Thanks to Rakesh Sharma`s answer, substituting the loop body with:

find . -mindepth 5 -maxdepth 5 -path "*/spades/filtered/$i" -type f -exec cp -t "$HOME/destination/" {} +;

speeds things up.

  • Hi FloHe, I want to search within the partial directory path the files which are in my list. – AudileF Jul 18 '17 at 12:06
  • @AudileF Why do you want to search within the partial dir path when the list file already have them with the partial path as a constant you mentioned earlier on? – user218374 Jul 18 '17 at 12:12
  • No my list is just names only. There is no path within the list. I see my original question is misleading. Ill change it now. – AudileF Jul 18 '17 at 12:15
  • @AudileF: So you have them without the partial dir path prefix in the file names.list? But then it isn't clear in which partial dir path to search for the individual files. – FloHe Jul 18 '17 at 12:17
  • 2
    @AudileF You could make the following changes to speed things up; find . -mindepth 5 -maxdepth 5 -path "*/spades/filtered/$i" -type f -exec cp -t "$HOME/destination/" {} +; where you are basically giving a chunk of files to cp rather than just 1 and the min/max-depths allow find to jump right in to the right hierarchy rather than recurse it's way through. – user218374 Jul 18 '17 at 13:40

You could do away with the for loop and do everything within xargs:

xargs -a names.list -L 1 -I @ find . -path \*/spades/filtered/@ -type f -exec cp -fpvt "$HOME/destination/" {} +

Assuming GNU xargs, find, and cp utilities.

-a will read the filename a line at a time.

-L 1 option makes xargs pass one newline-separated argument to find.

-I @ option will condense that argument in the symbol @ which can be stuck in the utility invoked by xargs, in this case, find. More specifically, the -path option of find is modified by the @ symbol for every line of names.list read.

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.