我已經學會了使用 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
多的命令。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.