LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 03-27-2017, 10:22 PM   #1
fanoflq
Member
 
Registered: Nov 2015
Posts: 397

Rep: Reputation: Disabled
grep and copy in one line


Code:
~ $ grep -lri hello ~/dir0 
/home/user1/dir0/hello1
/home/user1/dir0/hello2
/home/user1/dir0/hello3
Code:
~ $ grep -lri hello ~/dir0 | xargs cp -t ~/hellofilesfromdir0/
~ $ ls ~/hellofilesfromdir0/
hello1  hello2  hello3
I rather not remember using the t option for cp.
Is there another way to copy files found by grep like maybe
in the form below with outputs from grep going into
a placeholder {}
.
But this form does not works since it is not allowed!
Code:
~ $ grep -lri hello ~/dir0 | xargs cp {} ~/hellofilesfromdir0/

Is it also possible to do internal file search and copy without xargs, grep and cp?

Last edited by fanoflq; 03-27-2017 at 10:26 PM.
 
Old 03-28-2017, 01:17 AM   #2
syg00
LQ Veteran
 
Registered: Aug 2003
Location: Australia
Distribution: Lots ...
Posts: 20,831

Rep: Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007Reputation: 4007
Quote:
Originally Posted by fanoflq View Post
But this form does not works since it is not allowed!
Code:
~ $ grep -lri hello ~/dir0 | xargs cp {} ~/hellofilesfromdir0/
Try
Code:
~ $ grep -lri hello ~/dir0 | xargs -I {} cp {} ~/hellofilesfromdir0/
Quote:
Is it also possible to do internal file search and copy without xargs, grep and cp?
Awk, perl, python, ... start coding.
 
1 members found this post helpful.
Old 03-28-2017, 02:02 AM   #3
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051Reputation: 6051
i think i'd rather use a miniscript "oneliner" instead of pipes.
something like this (pseudo bash, not tested):
Code:
for i in grep something; do cp $i $i.new ; done
see, all in 1 line!
 
1 members found this post helpful.
Old 03-28-2017, 02:08 AM   #4
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,452

Rep: Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061
cp has a -t option that works nicely with xargs and find -exec
Code:
grep -lri hello ~/dir0 | xargs cp -t ~/hellofilesfromdir0
 
Old 03-28-2017, 02:30 AM   #5
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 20,232

Rep: Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836Reputation: 6836
probably:
cp -t <targetdir> $(grep ...)
 
Old 03-28-2017, 07:40 AM   #6
fanoflq
Member
 
Registered: Nov 2015
Posts: 397

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by ondoho View Post
i think i'd rather use a miniscript "oneliner" instead of pipes.
something like this (pseudo bash, not tested):
Code:
for i in grep something; do cp $i $i.new ; done
see, all in 1 line!
This works.

Code:
~/dir0 $ ls ~/hellofilesfromdir0/
~/dir0 $ for i in $(grep -ilr  "hello" ~/dir0) ; do cp $i ~/hellofilesfromdir0/; done
~/dir0 $ ls ~/hellofilesfromdir0/
hello1  hello2  hello3
 
Old 03-28-2017, 10:46 AM   #7
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,452

Rep: Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061
find -exec safely handles special file names like "two words.txt"
Code:
find ~/dir0 -type f -exec grep -qi hello {} \; -exec ln -t ~/hellofilesfromdir0 {} +
Further cp is replaced by an efficient ln (that increases the link count but only works within the file system; otherwise consider symlinks aka ln -s).
 
Old 03-28-2017, 01:11 PM   #8
fanoflq
Member
 
Registered: Nov 2015
Posts: 397

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by MadeInGermany View Post
find -exec safely handles special file names like "two words.txt"
Code:
find ~/dir0 -type f -exec grep -qi hello {} \; -exec ln -t ~/hellofilesfromdir0 {} +
Further cp is replaced by an efficient ln (that increases the link count but only works within the file system; otherwise consider symlinks aka ln -s).
Your command works. Thank you.

When grep output is silent, where does its result go in the shell?
What shell symbol(s) hold those grep outputs?

I am not able to parse this:
Code:
-exec ln -t ~/hellofilesfromdir0 {} +
The braces in last exec command, {}, seems to imply it is
a placeholder for output of grep.

I did not know {} is a catch all for silent grep output. Or is it?
I am not able to find information in bash on this form of usage.
Then there is the plus, +, symbol at the end.
How does {} + interact?

What man page has this information?
Man bash does not explain much about exec.
Thank you.
 
Old 03-28-2017, 02:34 PM   #9
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,452

Rep: Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061Reputation: 1061
The grep -q passes nothing but the exit status. A zero(="positive") exit status lets find continue with the next -exec
find substitutes each {} with the actual pathname.
{} + collects the arguments and calls the binary (here: cp or ln) with the maximum of arguments, just like xargs (without -l) does.
The first {} ends with \; because we immediately need the exit status for the current argument(=pathname).
The correct man page is
Code:
man find
 
1 members found this post helpful.
Old 03-28-2017, 03:03 PM   #10
fanoflq
Member
 
Registered: Nov 2015
Posts: 397

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by MadeInGermany View Post
The grep -q passes nothing but the exit status. A zero(="positive") exit status lets find continue with the next -exec
find substitutes each {} with the actual pathname.
{} + collects the arguments and calls the binary (here: cp or ln) with the maximum of arguments, just like xargs (without -l) does.
The first {} ends with \; because we immediately need the exit status for the current argument(=pathname).
The correct man page is
Code:
man find
Thank you.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to grep sections of a line out and copy to new file Leisurely Gentlemen Linux - Newbie 4 05-08-2012 03:44 PM
[SOLVED] Copy and replacing specific line from file1 to file2 line by line vjramana Programming 10 03-28-2011 07:49 AM
grep query to list 1 line [which is fixed] and the next line after it [variable text] Glenn D. Linux - Software 3 01-20-2011 06:21 AM
Want to print fouth line after resulted line using grep with tail command saurabhmehan Linux - Newbie 10 08-04-2010 11:38 PM
Grep's line numbers parsed into one line of output. judgex Programming 8 08-14-2006 04:22 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 02:04 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration