объединение find с другими командами: когда использовать -exec, а когда использовать pipe?

объединение find с другими командами: когда использовать -exec, а когда использовать pipe?

Я научился использовать команду find отдельно для поиска файлов и каталогов, однако когда дело доходит до выполнения каких-либо действий с файлами/папками, я теряюсь.

Дана следующая команда:

find . -type f -iname "*.cr2" 

Если я хочу скопировать найденные выше файлы в новый каталог, я бы, естественно, подумал, что нужно использовать copy( cp) и pipe |.

find . -type f -iname "*.cr2" | cp \destination_directory

Для меня это означало бы, что все мои фотографии со всего диска будут размещены в одной папке и будут готовы к организации.

Однако люди продолжают говорить мне, что нужно использовать -execпараметр, поэтому у меня вопрос: как узнать, когда следует передавать данные по конвейеру |, а когда использовать -execкоманду, как показано ниже?

 find . -name "*.pdf" -type f -exec cp {} ./pdfsfolder \;

РЕДАКТИРОВАТЬ

Предложенное решение (ниже) копирует только файлы, имена которых уникальны. и оно говорит, что cp не будет копировать file.txt и заменять на file.txt. В случае, если вы копируете много файлов и не знаете, будут ли файлы с таким же именем, как вы можете скопировать что-то и сказать переименовать его, если имя файла существует?

Предлагаемое решение

find . -type f -iname "*.txt" -print0 | xargs -0 cp -t /home/josh/Documents/copy/

/home/josh/documents/copy — это каталог, в который я хочу переместить данные.

решение1

В ваших предположениях есть ошибки, но сначала немного предыстории:

Вам следует различать два варианта использования -exec:

  • с \;будет {} заменен одним найденным элементом
  • при +этом {}будет заменено множеством элементов (столько, сколько может вместить командная строка).

Поэтому ваш пример -execиспользования вызывает столько cpкоманд, сколько элементов найдено find.

Использование find ... -exec cmd {} ... +аналогично по эффективности передаче выходных данных find в команду, обрабатывающую несколько входных имен.

Вам также следует принять во внимание, что -execотлично обрабатывает имена файлов/пути с пробелами, но когда вы передаете вывод из find в другую программу, это может вызвать проблемы. Поэтому некоторым программам, которые ожидают список имен файлов из stdin, можно предоставить возможность разделить эти имена файлов NUL (часто -0или --null). И findимеет и возможность передать их следующей программе таким образом, указав:-print0


Теперь перейдем к вашим примерам:

find . -type f -iname "*.cr2" | cp destination_directory

не копирует найденные файлы, так как cp не читает из стандартного ввода. Вам придется использовать:

find . -type f -iname "*.cr2" | xargs cp -t destination_directory

или для обработки путей с пробелами:

find . -type f -iname "*.cr2" -print0 | xargs -0 cp -t destination_directory

Примерно с такой же эффективностью можно было бы сделать:

find . -type f -iname "*.cr2" -exec cp -t destination_directory {} +

(Как указал G-Man, слово {}должно быть в конце, перед+ ») Все вышеперечисленное делаетнетДля этого я создаю иерархию в целевом каталоге и по давней привычке, даже если исходный каталог плоский, вместо этого я использую cpio:

find . -type f -iname "*.cr2" -print0 | cpio -pdmv0 destination_directory

который наглядно перечисляет, что он делает по ходу дела.


Соответствующие части из man find:

-exec command ;
       Execute command; true if 0 status is returned.   All  following
       arguments  to  find  are  taken  to be arguments to the command
       until an argument consisting of `;' is encountered.  The string
       `{}'  is  replaced  by  the  current  file name being processed
       everywhere it occurs in the arguments to the command, not  just
       in  arguments  where  it is alone, as in some versions of find.
       Both of these constructions might need to be  escaped  (with  a
       `\')  or  quoted  to  protect them from expansion by the shell.
       See the EXAMPLES section for examples of the use of  the  -exec
       option.   The  specified  command  is run once for each matched
       file.  The command  is  executed  in  the  starting  directory.
       There  are unavoidable security problems surrounding use of the
       -exec action; you should use the -execdir option instead.

-exec command {} +
       This variant of the -exec action runs the specified command  on
       the  selected files, but the command line is built by appending
       each selected file name at the end; the total number of invoca‐
       tions  of  the  command  will  be  much less than the number of
       matched files.  The command line is built in much the same  way
       that xargs builds its command lines.  Only one instance of `{}'
       is allowed within the command.  The command is executed in  the
       starting directory.

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