LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - General (https://www.linuxquestions.org/questions/linux-general-1/)
-   -   useful shortcut - pipe results of search to cp (https://www.linuxquestions.org/questions/linux-general-1/useful-shortcut-pipe-results-of-search-to-cp-295092/)

disorderly 02-26-2005 08:33 AM

useful shortcut - pipe results of search to cp
 
hey i wanted to share this because i've found it invaluable but would like take it 1 step further if someone could help.
after doing a search for files you can pipe the search results through other commands using what's called a subshell (a second running version of your shell)
for example if you try to pipe a your search results through cp it will complain that it is mising a parameter:
Code:

[root@itchy web]# locate filename.jpg) | cp $1 destination/
cp: missing destination file
Try `cp --help' for more information.
[root@itchy web]#

i tried using all sorts of ways to get cp to take a parameter but my linux knowledge is very limited

but if you put in this syntax it will work!:
Code:

cp $(locate filename.jpg) destination/
and all your files named filename.jpg will be hunted down and copied into destination/ :)

i was trying to find a faster way copy the results of "ldd" so i wouldn't have to manually hunt down the files but using that same command results in this:
Code:

[root@itchy web]#cp $(ldd /usr/bin/scp) test/
cp: cannot stat `libcrypto.so.4': No such file or directory
cp: cannot stat `=>': No such file or directory
cp: cannot stat `(0x0459f000)': No such file or directory

i'm guessing because it is a link? any ideas how to copy the ldd results??
thanks,
disorderly

caps_phisto 02-26-2005 10:03 AM

Here you go buddy:

Code:

cp $(ldd /usr/bin/scp | cut -d \( -f1- | cut -d \> -f2-) destination/
That should do the trick. By the way very nice way of copying...I have never thought to do it this way. Very clean.

disorderly 02-26-2005 04:59 PM

that rocks! thanks!
do you think you could explain to me how that works?

caps_phisto 02-26-2005 05:47 PM

Yeah no problem.

I take it you know what the ldd command does so we will skip that one.

I took the output of the ldd command and piped it to cut. Cut allows for manipulation of text input to "cut" out what you do not want.

The first cut parses the ldd output looking for the "(" character. But, you will see that there is a "\" preceding it. this "\" character is used to "escape out" the "(" character. In other words it tells BASH to treat the "(" character as just that a character and not tack on its special meaning (which is usually used to group commands together). Once parsed it then separates the text (internally) into two fields, one and two. The "-f1-" tells cut I only want field one and not two. This removes the (0xha89078) stuff at the end of the ldd output

I then take that output and pipe it to another cut. This time parsing for the ">" character. Again because this character has special meaning to BASH I need to "escape" it out, and hence again it is preceded by the "\" character. Again cut separates this output into two fields. I use the "-f2-" to tell cut I want the second field, which is the absolute path to where those files are located and not just their names. This will remove the name of the library and the => symbols of the ldd output.

This leaves you with just the nice little paths to the files you wish to copy.

NOTE: reversing the two cut commands will not work. I can't really explain why, as it should do the same thing. But, alas it does not.

Sorry for not explaining this in my original post, but I was on lunch break when I wrote that post and did not have time to explain.

disorderly 02-26-2005 06:37 PM

dude that is feckin GREAT. i can think of a dozen ways to use that 'cut' command :cool:
well to take this new piece of knowledge even further....

let take for example
Code:

[bach@itchy ~]$ ldd /bin/ls
        librt.so.1 => /lib/tls/librt.so.1 (0x008f6000)
        libacl.so.1 => /lib/libacl.so.1 (0x00d07000)
        libselinux.so.1 => /lib/libselinux.so.1 (0x00879000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00a87000)
        libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00cc9000)
        /lib/ld-linux.so.2 (0x00a6a000)
        libattr.so.1 => /lib/libattr.so.1 (0x00d01000)

with that cut command you will get:
Code:

[bach@itchy ~]$ cp $(ldd /bin/ls | cut -d \( -f1- | cut -d \> -f2-) temp
cp: cannot stat `(0x008f6000)': No such file or directory
cp: cannot stat `(0x00d07000)': No such file or directory
cp: cannot stat `(0x00879000)': No such file or directory
cp: cannot stat `(0x00a87000)': No such file or directory
cp: cannot stat `(0x00cc9000)': No such file or directory
cp: cannot stat `(0x00a6a000)': No such file or directory
cp: cannot stat `(0x00d01000)': No such file or directory
[bach@itchy ~]$ cd temp
[bach@itchy temp]$ ls
ld-linux.so.2  libacl.so.1  libattr.so.1  libc.so.6  libpthread.so.0  librt.so.1  libselinux.so.1

the copy was made but to clean up the resulting code i tried grouping the 'cut' part with {}, or [] but no success. any ideas?
thanks!!
(i'm thinking this is how some of the code was used to 'create a chrooted jail' was written - it would search for the relavant commands in directories, then ldd's the commands, then copy them to the correct folders!)

caps_phisto 02-26-2005 08:08 PM

Oh sorry I see the problem. The line I gave you:
Code:

cp $(ldd /usr/bin/scp | cut -d \( -f1- | cut -d \> -f2-) destination/
has two errors. They are both at the -f flags for the cut command. The line should look like this:
Code:

cp $(ldd /usr/bin/scp | cut -d \( -f1 | cut -d \> -f2) destination/
That was my bad. Apparently if you have that extra "-" at the end of "-f1" it will not cut field one out. It does not seem to affect "-f2" in this case, but to be sure I tried to command without it and it works the same.

With this new knowledge I tried reversing the two cut commands. Now if you remember:
Quote:

NOTE: reversing the two cut commands will not work. I can't really explain why, as it should do the same thing. But, alas it does not.
The extra "-" explains why before switching them would not work. Without that little "-" it does not matter the position of the cut commands. The cut -d \> -f2 can now come before the cut -d \( -f1 and vice versa.

I hope you have had as much fun with this as i have. If you have any other type of scripting questions post them here and I'll see wha tI can do.

minnarky 11-13-2010 11:09 AM

another way
 
I know this is an old thread, but I thought I would add my way of doing it.

Code:

cp $(find /path/to/source/files -iname filename.ext) /path/to/destination
So to find all pdf files in the current directory (and all subdirectories) and copy them into a directory called "pdf_files" in my home directory, it would look like this:

Code:

cp $(find ./ -iname *.pdf) ~/pdf_files
Just make sure your destination lies outside your current directory.


All times are GMT -5. The time now is 05:28 AM.