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
  • 320,670
  • 36
  • 633
  • 936
Akand
  • 69
  • 2
  • 9
  • 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. – roaima 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". – roaima 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
  • 320,670
  • 36
  • 633
  • 936
  • 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