How to Pipe the Results of 'Find' to Mv in Linux

How to pipe the results of 'find' to mv in Linux

find ./ -name '*article*' -exec mv {}  ../backup  \;

OR

find ./ -name '*article*' | xargs -I '{}' mv {} ../backup

Pipe 'find' command result list to move (mv) command – Terminal (zsh)

It's much easier to just do this:

  1. To your .zshrc file, add
    setopt extendedglob
    then restart your shell.
  2. This enables you to use the ^ operator:
    mv ^A*(-.) Strings
  • (-.) matches plain files or symlinks pointing to plain files. If you don't want the symlinks included, use (.) instead.
  • See http://zsh.sourceforge.net/Doc/Release/Expansion.html#Filename-Generation for more info on the extended glob syntax.

    ⚠️ Note that extended glob syntax is similar to but not exactly the same as regular expression syntax!

How do you send the output of ls to mv?

One way is with backticks:

mv `ls *.boo` subdir

Edit: however, this is fragile and not recommended -- see @lhunath's asnwer for detailed explanations and recommendations.

BASH Linux - How to pass the result of find into a mv destination via echo

ShellCheck helpfully points out three issues with your command:

  1. Your -execdir ignores everything before the -or

  2. Your \; has to be a separate argument

  3. Your `..` will expand once before find runs, not per file found.

Additionally,

  • The {} in the tr is interpretted by find
  • tr arguments should not have [] around them

Accounting for all this:

find . \( -name '*.pdf' -or -name '*.PDF' \) \
-execdir sh -c 'mv -v "$1" "$(echo "$1" | tr " " "_" | tr -d "{()},\!'\''" | tr "A-Z" "a-z" | sed "s/_-_/_/g")"' _ {} \;

Linux why can't I pipe find result to rm?

To expand on @Alex Gitelman's answer: yes, there's a difference between "standard input" and the command line.

When you type rm a.txt b.txt c.txt, the files you list after rm are known as arguments and are made available to rm through a special variable (called argv internally). The standard input, on the other hand, looks to a Unix program like a file named stdin. A program can read data from this "file" just as it would if it opened a regular file on disk and read from that.

rm, like many other programs, takes its arguments from the command line but ignores standard input. You can pipe anything to it you like; it'll just throw that data away. That's where xargs comes in handy. It reads lines on standard input and turns them into command-line arguments, so you can effectively pipe data to the command line of another program. It's a neat trick.

For example:

find . -name ".txt" | xargs rm
find . -name ".txt" | grep "foo" | xargs rm

Note that this will work incorrectly if there are any filenames containing newlines or spaces.
To deal with filenames containing newlines or spaces you should use instead:

find . -name ".txt" -print0 | xargs -0 rm

This will tell find to terminate the results with a null character instead of a newline.
However, grep won't work as before then. Instead use this:

find . -name ".txt" | grep "foo" | tr "\n" "\0" | xargs -0 rm

This time tr is used to convert all newlines into null characters.

Command line: piping find results to rm

You are actually piping rm's output to the input of find. What you want is to use the output of find as arguments to rm:

find -type f -name '*.sql' -mtime +15 | xargs rm

xargs is the command that "converts" its standard input into arguments of another program, or, as they more accurately put it on the man page,

build and execute command lines from standard input

Note that if file names can contain whitespace characters, you should correct for that:

find -type f -name '*.sql' -mtime +15 -print0 | xargs -0 rm

But actually, find has a shortcut for this: the -delete option:

find -type f -name '*.sql' -mtime +15 -delete

Please be aware of the following warnings in man find:

  Warnings:  Don't  forget that the find command line is evaluated
as an expression, so putting -delete first will make find try to
delete everything below the starting points you specified. When
testing a find command line that you later intend to use with
-delete, you should explicitly specify -depth in order to avoid
later surprises. Because -delete implies -depth, you cannot
usefully use -prune and -delete together.

P.S. Note that piping directly to rm isn't an option, because rm doesn't expect filenames on standard input. What you are currently doing is piping them backwards.

How to pipe list of files returned by find command to cat to view all the files

  1. Piping to another process (Although this WON'T accomplish what you said you are trying to do):

    command1 | command2

    This will send the output of command1 as the input of command2

  2. -exec on a find (this will do what you are wanting to do -- but is specific to find)

    find . -name '*.foo' -exec cat {} \;

    (Everything between find and -exec are the find predicates you were already using. {} will substitute the particular file you found into the command (cat {} in this case); the \; is to end the -exec command.)

  3. send output of one process as command line arguments to another process

    command2 `command1`

    for example:

    cat `find . -name '*.foo' -print`

    (Note these are BACK-QUOTES not regular quotes (under the tilde ~ on my keyboard).)
    This will send the output of command1 into command2 as command line arguments. Note that file names containing spaces (newlines, etc) will be broken into separate arguments, though.

How to move or copy files listed by 'find' command in unix?

Adding to Eric Jablow's answer, here is a possible solution (it worked for me - linux mint 14 /nadia)

find /path/to/search/ -type f -name "glob-to-find-files" | xargs cp -t /target/path/

You can refer to "How can I use xargs to copy files that have spaces and quotes in their names?" as well.



Related Topics



Leave a reply



Submit