如何根據大小遞歸移動文件並保持結構

如何根據大小遞歸移動文件並保持結構

我想從一個目錄樹中移動大於“300Mb”的文件,其中每個文件都位於子資料夾中

範例:我有一個目錄結構:

dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3

這是預期的結果,目錄樹的“移動”,其中每個檔案都移動到子資料夾:

dirB/            #  normal directory
dirB/file1       #  moved from dirA/file1
dirB/x/          #  normal directory
dirB/x/file2     #  moved from dirA/x/file2
dirB/y/          #  normal directory
dirB/y/file3     #  moved from dirA/y/file3

find /path/ -type f -size +300m然後呢?不幸的是,有些文件包含您可以在鍵盤上找到的各種字元。

我一直在看這個有人在談論cpio但我不知道那個程式...

PS:安裝了 GNU Parallel 是否可以加快速度?

答案1

最簡單的方法是桀騁。您可以使用全域限定符根據文件類型和大小等標準來匹配文件。這通配符模式 **/符合任何層級的子目錄。這歷史修正 ht是提取目錄和檔案名稱的基本部分的簡單方法。需要時調用mkdir -p建立目錄。

cd dirA
for x in **/*(.Lm+300); do
  mkdir -p ../dirB/$x:h &&
    mv -- $x ../dirB/$x
done

便攜式方式是使用find.用於-exec為每個檔案呼叫 shell 片段。

cd dirA
find . -type f -size +300000k -exec sh -c 'for x do
  mkdir -p "../dirB/${x%/*}"
  mv "$x" "../dirB/$x"
done' sh {} +

並行化對於輸入/輸出很少有用:它可以讓您利用多個 CPU,但 CPU 很少成為 I/O 瓶頸。

答案2

Perlrename是顯而易見的選擇。它可以安裝為renrenamepren

find dirA -type f -size +300M | ren 's:^dirA/:dirB/:'

但是,如果檔案移動到不同的安裝點,它就不起作用,如果目錄不存在,它就會失敗。

GNU Parallel 會更慢:

cd dirA
find . -type f -size +300M | parallel mkdir -p ../dirB/{//}
find . -type f -size +300M | parallel mv {} ../dirB/{}

但即使它需要執行複製然後刪除例程以將檔案轉移到不同的檔案系統上,它也會起作用。

答案3

簡而言之:

find dirA -type f -size +300m -printf "mv %p dirB/%P\n" | sh

但是,在開始之前,dirB 中的所有子目錄都必須存在。為此,我建議您執行以下兩個步驟:

cd dirA
find . -type f -size +300m -printf "mkdir -p ../dirB/%h\nmv %p ../dirB/%P\n" | sh

關於cpio(實際上是解決子目錄問題):

(cd dirA; find . -type f -size +300m) | cpio -p -md  dirB

(關於您提到的同一線程中的 cp(1) ,這對您不利,因為它會複製 全部 文件 在 dirB 下建立名為 dirA 的子目錄。旗幟-T可以解決這個問題)

答案4

這應該可以覆蓋它。

find /path -type f -size +300m | while read A ; do DEST=${A/dirA/dirB} ; echo mkdir -p $(dirname $DEST) 2>/dev/null; echo mv $A $DEST ; done

首先按原樣運行它,進行健全性檢查,如果對建議的命令感到滿意,則在不包含echo元素的情況下重新運行它。

在您的檔案結構範例中,將產生以下命令

mkdir -p ./dirB
mv ./dirA/file1 ./dirB/file1
mkdir -p ./dirB/x
mv ./dirA/x/file2 ./dirB/x/file2
mkdir -p ./dirB/y
mv ./dirA/y/file3 ./dirB/y/file3

相關內容