I am able to locate files in a folder containing a specific text string using this command:
grep -lir 'string' ~/directory/*
How do I move the files that appear in the above result to another location?
I am able to locate files in a folder containing a specific text string using this command:
grep -lir 'string' ~/directory/*
How do I move the files that appear in the above result to another location?
Use xargs
in concert with mv
's third syntax: mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
Be careful about files containing special characters (spaces, quotes). If this is your case, filtering the list with sed
(adding quotes around filenames with s/^/'/;s/$/'/
) might help, but you'd have to be sure, these quotes won't appear in the filenames. GNU grep
has the -Z
/--null
option to NUL-terminate filenames.
An alternative to the third syntax for mv
is using xargs
with the placeholder string (-I
).
Another option is command substitution - $( )
or backticks ``
(in bash) as mentioned in ire_and_curses' answer.
As always, beware of grep -r
. -r
is not a standard option, and in some implementations like all but very recent versions of GNU grep
, it follows symbolic links when descending the directory tree, which is generally not what you want and can have severe implications if for instance there's a symlink to "/" somewhere in the directory tree.
In the Unix philosophy, you use a command to search directories for files, and another one to look at its content.
Using GNU tools, I'd do:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
But even then, beware of race conditions and possible security issues if you run it as one user on a directory writeable by some other user.
xargs
exited before reading to the end of its arg-file which should not happen unless xargs is killed itself or fails for any reason in which case I'd expect you see an error about that as well.
– Stéphane Chazelas
Apr 20 '16 at 11:01
If your file names don't contain any special characters (whitespace or \[*?
), use command substitution:
mv `grep -lir 'string' ~/directory/*` destination/
Using only POSIX specified features, and making no assumptions about filenames:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
Notes:
You said "string" not "pattern," so the -F
(fixed string search) option of grep
seems appropriate.
If your destination directory is anywhere inside of your search directory, you may have some unpleasant race conditions.
Using GNU parallel:
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht/ @lin-dong for his original answer with xargs.
-Assume that you have destination directory as 'external' and need to move all XLS files, you can try below command
sudo mv find /var/log/ -type f -name "*.xls"
/external/
– Alan Dong Apr 28 '15 at 22:20grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name