サイズに応じてファイルを再帰的に移動して構造を維持する方法

サイズに応じてファイルを再帰的に移動して構造を維持する方法

各ファイルがサブフォルダにあるディレクトリツリーで、「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フラグメントを使用して各ファイルのシェルを呼び出すことです。

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

Perlはrename確かな選択です。renrenameまたは次のようにインストールできますpren

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のすべてのサブディレクトリが存在する必要があります。これを行うには、次の2つの手順に従うことをお勧めします。

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 というサブディレクトリを作成します。バナー-ティーこの問題を解決できます)

答え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

関連情報