Important: All commands in this post perform bulk actions and come with no warranty. If you are operating on critical files, or are unsure about what the commands do, consider replacing
mv
withcp
and inspecting the results. Also see the common gotchas section bellow…
The short answer
find /path/to/search -type f -print0 | \
xargs -0 grep -Z -l 'text you want to match' | \
xargs -0 -I {} mv {} /path/where/to/move
Explanation:
-
find /path/to/search -type f -print0
- Prints out all file name (only files not directories!), recursing into nested folders
-print0
must come at the end. It uses a null instead of newline separator to prevent whitespace issues- This list is passed to the next
xargs
-
xargs -0 grep -Z -l 'text you want to match'
xargs
feeds arguments from stdin into another command (grep
in this case)-0
makesxargs
use null as separator, needed since we used-print0
-
grep
-Z
makes grep output null separated values (like-print0
)-l
makes grep list only the names of the matching files
- The output of grep gets passed to the next
xargs
-
xargs -0 -I {} mv {} /path/where/to/move
-I {}
replace {} with the list value
Useful variants
1. Matching regular expressions
find /path/to/search -type f -print0 | \
xargs -0 grep -Z -l -E 'your*regex*pattern' | \
xargs -0 -I {} mv {} /path/where/to/move
Description: Add -E
if you want grep
to use extended regular expressions
2. Matching only files that DO NOT include the text
find /path/to/search -type f -print0 | \
xargs -0 grep -Z -L 'text you want to match' | \
xargs -0 -I {} mv {} /path/where/to/move
Description: Note the only difference is the big -L
replacing -l
3. Matching by file name instead of file content
find /path/to/search -type f -name '2021*' -print0 | \
xargs -0 -I {} mv {} /path/where/to/move
Description: Note it is important that -print0
always comes at the end of find
Common gotchas
- The commands above will find the files and move them into
/path/where/to/move
. Watchout that files with equal names will overwrite each other.
More resources
- https://stackoverflow.com/questions/11280389/remove-files-not-containing-a-specific-string
- https://askubuntu.com/questions/487035/mv-files-with-xargs
- http://mywiki.wooledge.org/UsingFind#Actions_in_bulk:_xargs.2C_-print0_and_-exec_.2B-
- https://www.gnu.org/software/grep/manual/grep.html
- https://www.plesk.com/blog/various/find-files-in-linux-via-command-line/