0

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.

A  
|-- 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.

Kusalananda
  • 333,661
Akand
  • 69
  • 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 04 '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 04 '18 at 16:47
  • grep? Your question does not mention grep. – Kusalananda May 04 '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 04 '18 at 18:54
  • Sure, but does that have anything to do with the actual issue of copying the files? – Kusalananda May 04 '18 at 19:00
  • @Kusalananda, No. – Akand May 04 '18 at 19:03
  • (1) Your question has been closed (put “on hold”) as “unclear what you’re asking”, which means we don’t understand your question.  The only way we have of knowing what you want to do is to look at the command you tried and work backwards from that to guess what you’re trying to accomplish.  If you want our help, please explain, in English sentences, what you want to accomplish.  (2) Kusalananda has asked you twice about grep.  One time you said that grep does not have anything to do with the actual issue of copying the files, … (Cont’d) – Scott - Слава Україні May 05 '18 at 18:00
  • (Cont’d) …  but you keep on talking about it and including it in your commands.  If it has something to do with your question, explain (in English sentences) what part of your question has what to do with searching file(s) for a pattern (I don’t see anything like that now).  If it doesn’t have anything to do with your question, stop talking about it!  (3) It might help if you presented an example directory tree and said how you want it to be handled.  There seem to be three conditions in your question: (a) existence / location of .out file, (b) existence / location of .gdx file, … (Cont’d) – Scott - Слава Україні May 05 '18 at 18:00
  • (Cont’d) …  and (c) results from grep — so your example should show a minimum of six cases to cover all the conditions.  … … … … … … … … … … … … … … … … … … … … … … … … Please do not respond in comments; [edit] your question to make it clearer and more complete. – Scott - Слава Україні May 05 '18 at 18:00
  • Your edit helps a little, but it still doesn't address the fundamental questions you've been asked in these comments. – Chris Davies May 05 '18 at 20:47
  • @roaima, I tried to make list to understand better. I am not sure how to place four spaces, hence I filled out with *. – Akand May 06 '18 at 16:36
  • Ok. Where do you want to copy the files? We can't usefully write code to copy files "somewhere". – Chris Davies May 06 '18 at 18:48

1 Answers1

0

With find:

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

Alternatively:

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:

Kusalananda
  • 333,661
  • 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 04 '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 04 '18 at 19:32
  • I added grep in my original question. – Akand May 04 '18 at 20:45
  • Can you please show for loop you added previously? – Akand May 04 '18 at 21:00
  • @Akand Thanks for adding relevant information to the question. I have updated my answer. – Kusalananda May 06 '18 at 16:18
  • What does mean ${1%.out}.gdx? In my case .out and .gdx are separate files. – Akand May 06 '18 at 16:27
  • @Akand It means, "take the value of $1 (which will be the path of one of the .out files), remove the .out suffix, and add a .gdx suffix". It creates the path to the .gdx file that lives in the same directory as the corresponding .out file. I have assumed that they have the same filename prefix (as in your directory list). – Kusalananda May 06 '18 at 17:01
  • @Kusalananda, I think I have understood. Yes, they have same name. However, if I want to transfer both .gdx and .out files, it should be cp "${1%{.out.,.gdx}}"? – Akand May 06 '18 at 18:04
  • @Akand In the question you explicitly say "and finally like to copy all *.gdx files". I will update my answer yet again. (done) – Kusalananda May 06 '18 at 18:18
  • @Kusulananda, what does mean by {} ';'? – Akand May 07 '18 at 14:08
  • @Akand {} is replaced by the found pathname and ; signals the end of the command line executed by -exec. I have described it in more detail here: https://unix.stackexchange.com/questions/389705/understanding-the-exec-option-of-find – Kusalananda May 07 '18 at 14:14