2017-05-04 57 views
1

我正在Mac電腦上使用Bash命令通過終端。鞏固成千上萬的文件與ln

我有200個目錄編號0-200。每個目錄包含> 5,000個以.fast5結尾的單個文件。我試圖找出將200個目錄組中的所有文件合併到一個名爲Consolidatedfiles的目錄中的最簡單方法。

我一直在嘗試不同的方法,但都沒有工作。下面的命令是我認爲最接近的命令。

find ./* -iname "*fast.5" | xargs -I {} ln ./Consolidatedfiles {} 

但是我搞亂了ln命令?我有0經驗配對find其他命令使用xargs

感謝您的幫助!

+0

對不起,我感到困惑。我的錯誤...我的意思是寫我想將文件收集到一個目錄中。我在上面的問題中糾正了這個問題。 – Paul

+0

還有一個問題:所有的舊文件應該移動到新的目錄或剛剛複製? – RomanPerekhrest

+1

而不是移動或複製文件我雖然使用ln鏈接到新目錄中的原始文件將是最好的解決方案。 – Paul

回答

5

下面是在一個單一的目標目錄中創建硬鏈接到您的所有文件的最有效的解決方案[1] ,假設你可以使用GNUln這MacOS的不配備(你可以,但是,通過Homebrew安裝):

find ./* -iname "*fast.5" -exec ln -t ./Consolidatedfiles/ {} + 

MACOS允許有高效xargs溶液-J(BSD特異性),其允許定義一個佔位符,擴展爲(典型地)所有參數,與-0find -print0組合以魯棒地傳遞文件名:

find ./* -iname "*fast.5" -print0 | xargs -0 -J {} ln {} ./Consolidatedfiles/ 

A-POSIX兼容解決方案慢得多,因爲它調用ln爲每個文件:

find ./* -iname "*fast.5" -exec ln {} ./Consolidatedfiles/ \; 

注意如何find-exec就像一個內置xargs,只有更健壯以及更高效的(因爲不需要管道和獨立xargs過程):

  • find ... -exec ... {} +像管道到| xargs ...

    • (通常)所有參數(儘可能多地適合單個命令行,儘可能少地使用調用)通過立即,總是在特定命令的處。

    • 注意{}必須+前的最後一個參數,這意味着該文件名只能在命令行的年底傳遞。

      • 這就是爲什麼GNUln以上要求,因爲只有它 - 作爲擴展到POSIX spec. - 允許前指定的目標目錄文件操作數的列表,-t <dir>
  • find ... -exec ... {} ... \;是像管道到| xargs -I {} ... {} ...

    • 目標命令爲每個文件調用一次,與{}所示的位置。
  • 使用-exec也較爲強勁xargs,因爲文件名總是正確傳遞,有關於與空格,引號,甚至嵌入式換行符的文件名沒有顧慮。

    • 相比之下,xargs默認由空格打破輸入流中的參數,並使用POSIX兼容的唯一選擇,你不能保證所有的參數都正確地傳遞;然而,find -print0xargs -0的結合非常穩健,而且這兩個非標準選項在Linux(GNU實用程序)和macOS/BSD上均受支持。 謝謝,Charles Duffy

至於你試過

ln操作數順序錯誤;該ln語法是:

ln <original> <link> 

,所以你應該使用ln {} ./Consolidatedfiles/

隨着該修正你的命令應該工作,但是使用基於命令以上優先效率的原因-exec


[1] 鏈路(相對於與ln -s創建的符號鏈接)都很少不再使用,但它們是在2個階段安全移動文件有用:硬鏈接指向到與原始文件完全相同的數據(實際上,甚至是原始文件都是硬鏈接),因此一旦確定硬鏈接在目標位置正確創建,就可以安全地刪除原始文件(其內容不會丟失,因爲新的硬鏈接仍指向它們)。

+0

還有一個非常高效的Perl版本,可避免爲每個文件創建一個進程...'find ... -print0 | perl -n0e'ln ...'' –

+0

@MarkSetchell:我假設你的意思是'link'(Perl函數)而不是'ln' - 這是一個選項,但它需要更多的工作,因爲'link'不接受目標_directory_作爲第二個參數。 原來,在macOS上結合'find -print0'和'xargs -0 -J {}'可能是最好的選擇 - 查看我的更新。 – mklement0