Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I have a text file containing file names only (it does not contain their paths). I need to find these files which may lie in any of the subfolders and then copy or move them to other location. To find the files I have tried

  1. cat 1.txt | xargs find -iname

  2. xargs find -iname < 1.txt

  3. xargs -a 1.txt find -iname

but they return " find: paths must precede expression: KUMARI_BRACK.jpg Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] ".

Any suggestion is greatly appreciated

share|improve this question

5 Answers 5

cat 1.txt | xargs -L 1 find /pathname -iname 

should help. It's not very efficient though, calling find again for every file in the list.

share|improve this answer

A more brute-force approach might be

find | egrep -f 1.txt

which will use the contents of the 1.txt file as a set of regexes to match. Since you ostensibly don't have any regex special characters in your filenames (except perhaps ".") this will, eventually, match any paths that find generates against the list of filenames.

It will be slow, however, depending on how many files you have in 1.txt.

A better approach might be to look at the names of the files, and if there's some general characteristics that can be gleaned (they all start the same, for example, or have similar suffixes) you can use those elements to do a better (more restricted) find. For example, if the files all end in .txt, and are owned by user foo, and will only be found in /tmp then

find /tmp -type f -user foo -name \*.txt 

would be more efficient, and also allow you to use the -exec arguments to find to do something to them, assuming you got only the matches you wanted.

find /tmp -type f -user foo -name \*.txt -exec mv {} /newdir \;
share|improve this answer

You have the "find" options incorrect. The first argument after "find" is the starting point for the search. So, something like:

cat 1.txt |xargs find /path/to/files -iname

should work. If you're searching the whole disk, then "find / -iname". If you're searching from the current working directory, then "find . -iname".

share|improve this answer
1  
The problem with that is that xargs will use more than one filename per call of find, leading to attempted calls to find like find /path -iname name1.txt name2.txt name3.txt, which is an illegal syntax for find. –  Sven Sep 15 '11 at 14:38
    
Ah, right, thank you. –  cjc Sep 15 '11 at 14:43
    
thanks for the quick reply. But i get the same message that paths must precede expression –  Prasad Sep 15 '11 at 15:05

It's brutal and inefficient, but works for me (in bash):

for file in `cat 1.txt` ; do find . -iname $file -print ; done

If you only want to find flat files (ie, not directories, special files, etc.) that match the name, change . -iname to . -type f -iname .

share|improve this answer
$cat list
FILE1
FILE2


$ cat list | tr -s '\n' '#' | sed -e 's/#/$\|\//g' | sed -e 's#|/$##'  |awk '{print "(/"$0")"}'
(/FILE1$|/FILE2$)

This above would generate argument for egrep below which will in one pass filter out necessary matches

$ find /tmp/ | egrep '(/FILE1$|/FILE2$)'
/tmp/test/FILE2
/tmp/test/FILE1
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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