將 find 與其他指令結合:何時使用 -exec 以及何時使用管道?

將 find 與其他指令結合:何時使用 -exec 以及何時使用管道?

我已經學會了使用 find 命令本身來查找文件和目錄,但是當涉及到對文件/資料夾執行某些操作時,我感到很困惑。

給出以下命令:

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

如果我想將上面找到的這些檔案複製到新目錄,我自然會想到使用 copy( cp) 和 pipeline |

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多的命令。cpfind

使用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.

相關內容