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

LinuxUnix

Linux Problem Overview


How do I pipe the results of a 'find' (in Linux) to be moved to a different directory? This is what I have so far.

find ./ -name '*article*' | mv ../backup

but its not yet right (I get an error missing file argument, because I didn't specify a file, because I was trying to get it from the pipe)

Linux Solutions


Solution 1 - Linux

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

OR

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

Solution 2 - Linux

xargs is commonly used for this, and mv on Linux has a -t option to facilitate that.

find ./ -name '*article*' | xargs mv -t ../backup

If your find supports -exec ... \+ you could equivalently do

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

The -t option is a GNU extension, so it is not portable to systems which do not have GNU coreutils (though every proper Linux I have seen has that, with the possible exception of Busybox). For complete POSIX portability, it's of course possible to roll your own replacement, maybe something like

find ./ -name '*article*' -exec sh -c 'mv "$@" "$0"' ../backup {} \+

where we shamelessly abuse the convenient fact that the first argument after sh -c 'commands' ends up as the "script name" parameter in $0 so that we don't even need to shift it.

Probably see also https://mywiki.wooledge.org/BashFAQ/020

Solution 3 - Linux

I found this really useful having thousands of files in one folder:

ls -U | head -10000 | egrep '\.png$' | xargs -I '{}' mv {} ./png

To move all pngs in first 10000 files to subfolder png

Solution 4 - Linux

mv $(find . -name '*article*') ../backup

Solution 5 - Linux

Here are a few solutions.

find . -type f -newermt "2019-01-01" ! -newermt "2019-05-01" \
    -exec mv {} path \;**

or

find path -type f -newermt "2019-01-01" ! -newermt "2019-05-01" \
    -exec mv {} path \;

or

find /Directory/filebox/ -type f -newermt "2019-01-01" \
    ! -newermt "2019-05-01" -exec mv {} ../filemove/ \;

The backslash + newline is just for legibility; you can equivalently use a single long line.

Solution 6 - Linux

xargs is your buddy here (When you have multiple actions to take)!

And using it the way I have shown will give great control to you as well.

find ./ -name '*article*' | xargs -n1 sh -c "mv {}  <path/to/target/directory>"

Explanation:

  1. -n1

Number of lines to consider for each operation ahead

  1. sh -c

The shell command to execute giving it the lines as per previous condition

  1. "mv {} /target/path"

The move command will take two arguments-

  1. The line(s) from operation 1, i.e. {}, value substitutes automatically

  2. The target path for move command, as specified

Note: the "Double Quotes" are specified to allow any number of spaces or arguments for the shell command which receives arguments from xargs

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1015214View Question on Stackoverflow
Solution 1 - LinuxAmitView Answer on Stackoverflow
Solution 2 - LinuxtripleeeView Answer on Stackoverflow
Solution 3 - LinuxSteffanView Answer on Stackoverflow
Solution 4 - LinuxVencatView Answer on Stackoverflow
Solution 5 - Linuxhizlan erpakView Answer on Stackoverflow
Solution 6 - Linuxnitinr708View Answer on Stackoverflow