膨大な数のファイルを含むフォルダーからファイルをコピー/tar するにはどうすればよいですか?

膨大な数のファイルを含むフォルダーからファイルをコピー/tar するにはどうすればよいですか?

そこで、私はちょっとした愚かなミスを犯しました。ソースからデータを収集するプロセス中に、すべてを外部ディスクのルートにダンプしてしまいました。現在、そこには 60 万以上のファイル (合計 23 GB) があります。私が実行したいオプションは次のとおりです。

  1. 一定数のファイルをディスクからハードディスクに移動します。
  2. サブフォルダー (各サブフォルダーに 1000 個のファイル) を作成し、それらの間でファイルを分散します。
  3. 全体またはその一部 (たとえば 50,000 ファイル) を tar で圧縮し、ディスクに移動します。

しかし、何をやっても、永遠にかかるように思えます。誰か、これらのいずれかを実行する最適/最も効率的な方法について教えてくれませんか? よろしくお願いします。

答え1

以下のコマンドは、 というサブディレクトリを作成し、次に..という番号newの付いたサブディレクトリを 50 個作成します。その後、現在のディレクトリから各ディレクトリに最大 1000 個のファイルを移動します。newnew/01new/50new/*

注1: ​​以下のいずれかの場合には動作しません。ファイル名改行 ( \n) が含まれます。

注2: これには GNUxargsと GNU が必要ですmv。Linux を実行しているので、これらは標準です。

必要に応じて、数字 (50 と 1000) とベース ディレクトリを変更できます。

#! /bin/sh

BASEDIR='new'
SUBDIRS=50
FILECOUNT=1000

mkdir -p "$BASEDIR"

for i in $(seq -w 1 "$SUBDIRS") ; do
   mkdir -p "$BASEDIR/$i"

   # move maximum of $FILECOUNT files to new/$i
   find . -maxdepth 1 -type f | head -n "$FILECOUNT" | xargs -d'\n' mv -t "$BASEDIR/$i"
done

移動したいファイルがすべて特定のパターンに一致する場合は、検索-nameまたは-regexオプションを使用して選択できます。オプションは . の直後に追加します。たとえば、ファイル-type fのみを移動したい場合は次のようにします。.txt

find . -maxdepth 1 -type f -name '*.txt' | head -n "$FILECOUNT" | xargs -d'\n' mv -t "$BASEDIR/$i"

非 GNU バージョンでは を使用できません。また、 オプションもmv -t使用できませんが、 を使用して改行を NUL 文字に変換し、 に送ることができます。これも、ファイル名に が含まれていないファイルに対応します。 は POSIX 以外の の FreeBSD 拡張であるため、そのオプションを安全に削除できますが、操作の実行速度は大幅に低下します。xargs -dtr '\n' '\0'xargs -0r\n-R -1xargsmv

#! /bin/sh

BASEDIR='new'
SUBDIRS=50
FILECOUNT=1000

mkdir -p "$BASEDIR"

for i in $(seq -w 1 "$SUBDIRS") ; do
   mkdir -p "$BASEDIR/$i"

   # move maximum of $FILECOUNT files to new/$i
   find . -maxdepth 1 -type f | head -n "$FILECOUNT" | tr '\n' '\0' | xargs -0r -R -1 -I % mv % "$BASEDIR/$i"
done

関連情報