Find the answer to your Linux question:
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 ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    HMW
    HMW is offline
    Just 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:
    Code:
    ls | grep -i foo
    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:
    mv | ls | grep -i foo ~/wherever
    This will def. not work, I know!

    I hope that made some sense, appreciate any input from all y'all.

    Thanks for reading this,

    HMW

  2. #2
    Trusted Penguin Irithori's Avatar
    Join Date
    May 2009
    Location
    Munich
    Posts
    3,345
    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.

  3. #3
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,380
    You can also execute code within a find command:

    Code:
    find . -iname '*foo*' -exec mv {} ~/wherever \;
    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.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  4. #4
    Just Joined!
    Join Date
    May 2011
    Posts
    3
    You can also do something like this using xargs


    Code:
    ls | grep -i foo | xargs -i mv {} bar/
    this will move all files matching "foo" to the bar directory.

    dizzio

  5. #5
    Just 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 $().

  6. #6
    Linux User
    Join Date
    Nov 2008
    Location
    Tokyo, Japan
    Posts
    260
    This is my favorite technique for executing a command on a list of files:
    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
    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.

    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:
    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 \;
    But for even slightly more complex tasks, the piping to a subshell works better.

  7. #7
    HMW
    HMW is offline
    Just 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

  8. #8
    Just 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).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •