I want to search by file extension and by texts and then copy a binary file inside the same folder. For instance, I am in directory A and finally like to copy all *.gdx files (in B,C,D) to somewhere.

|-- B                               
|   |-- file1.out (a text file)                     
|   |-- file1.gdx (a binary file)            
|-- C         
|   |-- file2.out (a text file)  
|   |-- file2.gdx (a binary file)  
|-- D         
|   |-- file3.out (a text file)  
|   |-- file3.gdx (a binary file)  

Here is my code:

cd 'find . -maxdepth 2 -name "*.out"|xargs grep "sometext"| awk -F'/' '{print $2}'|sort -u ' && ' find . -maxdepth 2 -name "*.gdx" -print0|xargs -0 cp -t /somewhere' 

The problem here, if first find captures multiple folders then copy only one *.gdx file from the first folder, not all *.gdx files from all folders. I believe it has to be done by loop, but don't know how to script.

  • Is it correct to assume that the directories have names ending with .out and that the files within those directories have name ending with .gdx? Are the .gdx files located at the top level of those folders or may they exist anywhere beneath the .out folders? – Kusalananda May 4 '18 at 15:36
  • @Kusalananda, Both *.out and *.gdx exist in beneath top level directory. The reason first I searched by *.out in first find is, the *.gdx is a binary file and cannot be grep by the same text as of *.out. The objective is, find directory which has .out file, cd there, and then cp files (.gdx, etc.) to somewhere. Thanks! – Akand May 4 '18 at 16:47
  • grep? Your question does not mention grep. – Kusalananda May 4 '18 at 16:49
  • @Kusalananda, sorry for not clarification. What I meant I can add grep for *.out file like find . -maxdepth 2 -name "*.out" | xargs grep "sometext" , but not for *.gdx file which is a binary. – Akand May 4 '18 at 18:54
  • Sure, but does that have anything to do with the actual issue of copying the files? – Kusalananda May 4 '18 at 19:00

With find:

find . -type f -name '*.out' -exec grep -q 'PATTERN' {} ';' \
    -exec sh -c 'cp "$1" "${1%.out}.gdx" /somewhere' sh {} ';'


find . -type f -name '*.out' -exec grep -q 'PATTERN' {} ';' \
    -exec sh -c 'for name do cp "$name" "${name%.out}.gdx" /somewhere; done' sh {} +

This would find all files in the current folder or below, whose names end with .out. If an .out file has a line matching PATTERN, the .gdx file in the same directory, with the same name prefix as the .out file, will be copied to /somewhere together with the .out file.

No test is done for whether there is already an existing directory entry under /somewhere with the same name as the files being copied, or whether the .gdx file actually exists to start with.

See also:

| improve this answer | |
  • Thanks. Here is script I am using find . -maxdepth 2 -type f '(' -name '*.out' -o -name '*.gdx')'|xargs grep "sometext" | xargs -exec cp -t /somewhere {} +. This prints folder names as expected but cannot execute copy. Error messages: cp: cannot stat '{}' : No such file or directory; cp: cannot stat '+' : No such file or directory, etc. – Akand May 4 '18 at 19:23
  • 1
    @Akand I asked you in comments to the question whether using grep was part of the issue of moving the files, and you said "no". You also do not mention grep in the question at all. Please update your question with the correct requirements. – Kusalananda May 4 '18 at 19:32
  • I added grep in my original question. – Akand May 4 '18 at 20:45
  • Can you please show for loop you added previously? – Akand May 4 '18 at 21:00
  • @Akand Thanks for adding relevant information to the question. I have updated my answer. – Kusalananda May 6 '18 at 16:18

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