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
mvwithcpand 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/moveExplanation:
-
find /path/to/search -type f -print0- Prints out all file name (only files not directories!), recursing into nested folders
-print0must 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'xargsfeeds arguments from stdin into another command (grepin this case)-0makesxargsuse null as separator, needed since we used-print0-
grep-Zmakes grep output null separated values (like-print0)-lmakes 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/moveDescription: 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/moveDescription: 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/moveDescription: 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/