Answers:
与往常一样,当心grep -r
。-r
这不是一个标准选项,在某些实现中,例如GNU的所有版本,但非常新的版本grep
,它在降下目录树时会遵循符号链接,这通常不是您想要的,并且可能会产生严重的影响,例如,如果存在到“ /在目录树中的某个位置。
在Unix哲学中,使用命令在目录中搜索文件,然后使用另一命令查看其内容。
使用GNU工具,我会做:
xargs -r0 --arg-file <(find . -type f -exec grep -lZi string {} +
) mv -i --target-directory /dest/dir
但是即使这样,如果您以一个用户在其他用户可写的目录上运行它,也要注意竞争状况和可能的安全问题。
xargs
在读取其arg文件的末尾之前退出时才会发生这种情况,除非xargs自身被杀死或由于任何原因而失败,否则这种情况不会发生,在这种情况下,我希望您也看到有关此错误的信息。
使用xargs
与演唱会mv
的第三句法:mv [OPTION]... -t DIRECTORY SOURCE...
grep -lir 'string' ~/directory/* | xargs mv -t DEST
注意包含特殊字符(空格,引号)的文件。如果是这种情况,请使用过滤列表sed
(使用来在文件名周围加上引号s/^/'/;s/$/'/
)可能会有所帮助,但是您必须确保,这些引号不会出现在文件名中。GNU grep
具有-Z
/ --null
选项以NUL终止文件名。
第三种语法的替代方法mv
是xargs
与占位符字符串(-I
)一起使用。
另一个选择是命令替换- $( )
或``
ire_and_curses的答案中提到的反引号(以bash表示)。
仅使用POSIX指定的功能,并且不假设文件名:
find ~/directory -type f -exec grep -qiF 'string' {} \; -exec mv {} /path/to/dest \;
笔记:
您说的是“字符串”而不是“模式”,因此-F
(固定字符串搜索)选项grep
似乎合适。
如果目标目录位于搜索目录内的任何位置,则可能会出现一些不愉快的竞争状况。
使用GNU parallel:
grep -i -Z -r -l 'string' . | parallel 'mv {} destination/{}'
ht / @ lin-dong对xargs的原始回答。
grep -i -Z -r -l 'string' . | xargs -I{} mv {} ./folder_name