Как правильно выполнить конвейерную передачу find с помощью grep и cp в этом варианте использования

Как правильно выполнить конвейерную передачу find с помощью grep и cp в этом варианте использования

Мне интересно рекурсивно выполнить grepping для строки в каталоге для шаблона, а затем cp'ing соответствующего файла в целевой каталог. Я думал, что могу сделать что-то вроде следующего, но это, похоже, не имеет смысла с инструментом поиска Linux:

find . -type f -exec grep -ilR "MY PATTERN" | xargs cp /dest/dir

Есть ли лучший способ сделать это? Или способ, который хотя бы работает, был бы хорошим началом.

решение1

Сделайте man xargsи посмотрите на -Iфлаг.

find . -type f -exec grep -ilR "MY PATTERN" {} \; | xargs -I % cp % /dest/dir/

Также после флага findожидается \;или .+-exec

решение2

Я не думаю, что вам нужно find. Рекурсивный grep:

grep -rl "MY PATTERN" .

решение3

xargsсчитывает свой стандартный ввод и помещает их в конец команды, которая должна быть выполнена. Как вы написали, вы в конечном итоге выполните

cp /dest/dir sourcefile1 sourcefile2 sourcefile3

что совсем не то, что вам нужно.

Вы можете использовать -Iопцию, чтобы указать заполнитель для xargs, например: xargs -I '{}' cp '{}' /dest/dir.

Кроме того, findон заботится о рекурсии, поэтому вам grepне понадобится -R.

Окончательное решение:

find . -type f -exec grep -il "MY PATTERN" '{}' + | xargs -I '{}' cp '{}' /dest/dir

решение4

Ни один из приведенных выше примеров не учитывает возможность grepгенерации -lдублирующихся результатов (файлов с одинаковыми именами, но в разных местах), и, следовательно, перезаписывания findхуком execфайлов в целевом каталоге.

Попытка решить эту проблему:

$ tree foo
foo
├── bar
│   ├── baz
│   │   └── file
│   └── file
├── destdir
└── file

3 directories, 3 files

$ while read a; do mv $a foo/destdir/$(basename $a).$RANDOM; done < <(grep -rl content foo)

$ tree foo
foo
├── bar
│   └── baz
└── destdir
    ├── file.10171
    ├── file.10842
    └── file.25404

3 directories, 3 files

Связанный контент