Results 1 to 8 of 8
Hi all!
I realize this might be too basic for this section, but nevertheless; I am wondering how to execute something that comes out of a pipe.
For instance, say ...
- 06-22-2011 #1Just Joined!
- Join Date
- Nov 2010
- Location
- 08 - Stockholm
- Posts
- 19
pipe question
Hi all!
I realize this might be too basic for this section, but nevertheless; I am wondering how to execute something that comes out of a pipe.
For instance, say that I do:
No problem there, but what if I want to move the files that are found (f.ex. Foo.txt foo.pl) to another directory. What I WANT to do is something like this:Code:ls | grep -i foo
This will def. not work, I know!Code:mv | ls | grep -i foo ~/wherever
I hope that made some sense, appreciate any input from all y'all.
Thanks for reading this,
HMW
- 06-22-2011 #2
So you want
- to move all files, directorys, links, etc,
- that dont have case insensitive "foo" as as part of the name to another place?
First question is then, if you want to preserve the directory structure.
If yes, rsync is your friend
For no (and as well as a more general approach):
Use find to list the files/dirs/etc you are interested in, and pipe that list to a while read construct
To make it even more general: of course it doesnt need to be find, that creates the list.You must always face the curtain with a bow.
- 06-22-2011 #3Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 8,974
You can also execute code within a find command:
The {} symbol is expanded into the path+filename, so this example would move all files with foo (in upper or lower case) in the name to ~/wherever.Code:find . -iname '*foo*' -exec mv {} ~/wherever \;Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!
- 06-22-2011 #4Just Joined!
- Join Date
- May 2011
- Posts
- 3
You can also do something like this using xargs
this will move all files matching "foo" to the bar directory.Code:ls | grep -i foo | xargs -i mv {} bar/
dizzio
- 06-23-2011 #5Just Joined!
- Join Date
- Feb 2007
- Location
- Cobleskill, NY
- Posts
- 51
Or try this:
mv $(ls | grep -i foo) ~/wherever
Here the source will be the result of what is in $().
- 06-23-2011 #6Linux Newbie
- Join Date
- Nov 2008
- Location
- Tokyo, Japan
- Posts
- 243
This is my favorite technique for executing a command on a list of files:
The idea is to pipes a list of files to a subshell, and the subshell (the part in parenthases) uses "read" to read every line given to it, storing each line in the variable "$F". You can then do whatever you want with $F.Code:find . -name '*.pdf' | (while read F; do echo $F; mv $F ../pdf/; done) #Or, you can save to a temporary file, then work on the file find . -name '*.pdf' >temp-file.txt (while read F; do echo $F; mv $F other-dir; done) <temp-file.txt
This technique can be gives you more control than "find" or "xargs".
Find's "exec" command is limited because it only allows you to execute a single program -- it does not allow per-item redirections, nor variables, nor conditionals like "if" or "case". But by piping to a subshell, you can execute a miniature script on each file, with redirections and variables and everything. Find also does not let you use the filename twice in the same command.
Xargs can have problems with very large lists. Xargs must first buffer the entire output of "find" in memory, and when "find" finally finishes, it will execute the given command, passing the whole buffer as a list of arguments. Piping to a subshell does not require copying the output of "find" to memory at all. Using the pipe, each found item is executed one at a time as soon as it is found, no need for extra memory, no need to wait for find to complete.
If all you need is to move a few files from one place to another, then any of these will work:But for even slightly more complex tasks, the piping to a subshell works better.Code:mv *.pdf *.html ../other-dir/ #or... mv -t ../other-dir/ $(find . -name '*.pdf' -o -name '*.html') #or... find . \( -name '*.pdf' -o -name '*.html' \) -exec mv '{}' other-dir \;
- 06-23-2011 #7Just Joined!
- Join Date
- Nov 2010
- Location
- 08 - Stockholm
- Posts
- 19
Thanks, to all of you. You all gave me very good answers, and now I have several to choose from. My favourite might be ProfTheory's answer, since I like the idea of working with ”return values”, but all were awesome. I love this place!
Best,
HMW
- 06-23-2011 #8Just Joined!
- Join Date
- Feb 2007
- Location
- Cobleskill, NY
- Posts
- 51
If that doesn't work you can try this instead:
for a in $(ls | grep -i foo); do mv $a ~/wherever; done
That executes repetitive mv commands with $a as the source from the list provided by $(ls | grep -i foo).


Reply With Quote