ファイルタイプ別に大きなディレクトリツリーを分割する

ファイルタイプ別に大きなディレクトリツリーを分割する

私のUbuntu 10.10デスクトップには、多数の生データファイル、処理済みデータファイル、および処理済みデータから生成されたさまざまなスクリプト、テーブル、グラフなどを含む大容量データディレクトリ(20-30Gb)があります。データカタログは長年にわたり蓄積されており、構造が間違っています。 「いつか」を整理しますが、常にもっと重要なことがあります。

今はオンラインバックアップサービスに移行していますが、バックアップに費やす時間と必要なオンラインストレージ容量を減らすために多くのスペースが必要ですが、簡単に置き換えられる元のデータを分割したいと思います。ディレクトリ構造内の通常の場所を維持しながら、他の場所に保持されているアイテム。つまり、私は次のような場所から始めたいのです。

/data/A/raw1.data
/data/A/raw2.data
/data/A/raw3.data
/data/A/processed.txt
/data/A/figure.eps
/data/A/plot.gnu
/data/B/raw4.data
/data/B/processed.txt
... etc.

到着

/data/A/processed.txt
/data/A/figure.eps
/data/A/plot.gnu
/data/B/processed.txt
... etc.

そして

/raw_data/A/raw1.data
/raw_data/A/raw2.data
/raw_data/A/raw3.data
/raw_data/B/raw4.data
... etc.

したがって、生データファイルは/ dataから/ raw_dataに置き換えられますが、ディレクトリ構造内の場所は保持され、処理されたデータと関連ファイルは同じ場所に保持されます。完全なファイル構造はこれよりはるかに複雑で体系的ではありませんが、すべての生データをファイルタイプ(主に.fitsと.sdf)で識別できるという利点があります。

正しいコマンドの組み合わせおよび/または数行のbashスクリプトを使用することはこれが些細なことであると確信していますが、コマンドラインの知識は基本的に制限されているので、混乱の危険を冒すのではなく尋ねたいと思います。 :)

しかし、元のデータから重複する項目を簡単に見つける方法はありますか?同じファイル名+サイズを持ち、必ずしもタイムスタンプではなくても、アーカイブからデータをダウンロードするとリセットされます。カスタムヘッダーのタイムスタンプに対して、dfitsとgrepを介して各冗長候補をパイプする必要があります。

答え1

rsync1つの方法は、次のように特別に作成された包含/除外ルールと同期した後にソースファイルを削除するオプションを使用することです。

rsync -av --include "*/" --include='*.fits' --include='*.sdf' \
    --exclude='*' --remove-source-files /data/ /raw_data/

他のタスクを含むループ内を段階的に移動するには、次のスクリプトが必要です。

DIR1="/data"
DIR2="/raw_data"

find "$DIR1" -type f \( -iname '*.fits' -or -iname '*.sdf' \) -print0 |
    while read -d $'\0' file; do
        mkdir -p "$DIR2/$(basename "$file")"
        mv "$file" "$DIR2/$(basename "$file")"
    done

答え2

十分に柔軟なルールを使用してターゲットディレクトリ名(、、、、zcp... )を構成できるファイルコピーツールがたくさんあります。残念ながら、必要に応じてターゲットディレクトリを移動(コピーではなく)して作成することを許可することはほとんどありません。したがって、2つのステップで実行されるいくつかの方法を紹介します。まず、必要なすべての必要な宛先ディレクトリを作成してから移動します。rsyncpax

パールの名前を変更する

rename必要なPerl部分を作成すると、DebianとUbuntuに付属のPerlプログラムが必要な場合は、ターゲットディレクトリを作成できます。

shopt -s globstar       # make **/ traverse directories recursively (requires bash 4)
rename 'BEGIN {use File::Path}
        s!^/data!/raw_data!;
        m!(.*)/!; mkpath($1)' /data/**/*.raw

zshではこの行はshopt -s globstar省略されています。**デフォルトは再帰巡回を意味します。 bash および zsh 以外のシェルでは、再帰巡回を使用する必要がありますfind(下記の例を参照)。単一レベルのディレクトリしかない場合は、これらすべてについて心配する必要はありません。

宛先ディレクトリの作成

zshから(説明:/ グローバル予選これはディレクトリのみが一致し、eglob修飾子は後で各名前に指定された変換を適用することを意味します。

mkdir /data/**/*(/e\''REPLY=${REPLY/data/raw_data}'\')

他のシェルの場合:

find /data -type d \
     -exec sh -c 'for d; do mkdir "/raw_data${d#/data}"; done' _ {} +

1レベルのサブディレクトリしかない場合ははるかに簡単です。

for d in /data/*/; do mkdir "/raw_data${d#/data}"; done

ファイルの移動(zsh)

autoload zmv
zmv -Q '/data/(**/)(*.raw)(.)' '/raw_data/$1$2'

ファイル移動(携帯用)

find /data -name '*.raw' \
     -exec sh -c 'for x; do mv "$x" "/raw_data${x#/data}"; done' _ {} +

関連情報