大容量ファイルをコピーせずに互いに添付

大容量ファイルをコピーせずに互いに添付

5つの大容量ファイル(ファイル1、ファイル2、..ファイル5)がそれぞれ約10Gで、ディスクに残っている空き容量が非常に少ないため、これらすべてのファイルを1つに接続する必要があります。元のファイルをアーカイブする必要なく、最終ファイルのみをアーカイブするだけです。

cat通常の接続はファイル順に行われますfile2. file5:

cat file2 >> file1 ; rm file2

残念ながら、この方法を使用するには少なくとも10Gの空き容量が必要ですが、私にはそのような空き容量はありません。ファイルを実際にコピーせずにリンクする方法はありますか?しかし、ファイルシステムは、file1が元のfile1の終わりから終わらず、file2が始まるところで続くことを何らかの方法で知らせることができますか?

PS重要な場合、ファイルシステムはext4です。

答え1

AFAIK残念ながら、最初からファイルを切り捨てることは不可能です(標準ツールでは適用できますが、システムコールレベルでは適用されません)。ねえ)。ただし、いくつかの複雑さが追加され、通常の切り捨て(スパスファイルを使用)を使用できます。間にすべてのデータを書き込むことなく、ターゲットファイルの最後に書き込むことができます。

まず、これら2つのファイルのサイズが正確に5GiB(5120MiB)で、一度に100MiBを移動するとします。以下を含むループを実行します。

  1. ソースファイルの終わりからターゲットファイルの終わりまでブロックをコピーします(消費されるディスク容量が増えます)。
  2. ソースファイルの一部を切り捨てる(ディスクスペースを解放)

    for((i=5119;i>=0;i--)); do
      dd if=sourcefile of=targetfile bs=1M skip="$i" seek="$i" count=1
      dd if=/dev/zero of=sourcefile bs=1M count=0 seek="$i"
    done
    

しかし、まず、より小さなテストファイルを試してみてください...

おそらくファイルのサイズが同じでもブロックサイズの倍数でもないかもしれません。この場合、オフセット計算はより複雑になる。その後、使用する必要がseek_bytesありますskip_bytes

これが気に入っていますが、詳細についてお手伝いが必要な場合は、もう一度お問い合わせください。

警告する

ブロックサイズによって、dd結果ファイルは断片化の悪夢になります。

答え2

プログラムが複数のファイルを処理できない場合は、ファイルを単一のファイルにマージするのではなく、名前付きパイプを使用して単一のファイルをエミュレートできます。

mkfifo /tmp/file
cat file* >/tmp/file &
blahblah /tmp/file
rm /tmp/file

Haukeが提案したようにlosstup / dmsetupも機能します。簡単な実験です。 "file1..file4"を作成し、いくつかの努力の終わりに以下を行いました。

for i in file*;do losetup -f ~/$i;done

numchunks=3
for i in `seq 0 $numchunks`; do
        sizeinsectors=$((`ls -l file$i | awk '{print $5}'`/512))
        startsector=$(($i*$sizeinsectors))
        echo "$startsector $sizeinsectors linear /dev/loop$i 0"
done | dmsetup create joined

/dev/dm-0には、ファイルを含む仮想ブロックデバイスが含まれています。

私はこれをうまくテストしていません。

別の編集:ファイルサイズは512で割ることができなければなりません。そうしないと、一部のデータが失われます。それなら行ってもいいですね。私は彼が以下でもこれを指摘しているのを見ています。

答え3

最大の空き容量と同じデータをコピーするには、何かを作成する必要があります。次のように動作する必要があります。

  • ここからデータの塊を読みますfile2pread()正しい位置を読み取る前にパススルーを使用)。
  • ブロックをに追加しますfile1
  • fcntl(F_FREESP)スペース割り当てを解放するために使用されますfile2
  • 繰り返す

答え4

私はこれがあなたが要求したよりも多くの解決策であることを知っていますが、問題を解決します(断片化や手間がほとんどまたはまったくありません)。

#step 1
mount /path/to/... /the/new/fs #mount a new filesystem (from NFS? or an external usb disk?)

それから

#step 2:
cat file* > /the/new/fs/fullfile

または圧縮が役に立つと思う場合:

#step 2 (alternate):
cat file* | gzip -c - > /the/new/fs/fullfile.gz

それから(そしてその時のみ)ついに

#step 3:
rm file*
mv /the/new/fs/fullfile  .   #of fullfile.gz if you compressed it

関連情報