/dev/stdin ファイルから tar を生成する

/dev/stdin ファイルから tar を生成する

STDINを介して任意のデータを渡し、通常のファイルのように圧縮する方法を探しています。

私はこれを試しました

$ echo test | tar -cf test.tar /dev/stdin

test.tarこれにより、内容を含むファイルが提供されますdev/stdin。ファイルstdinはリンクです/proc/self/fd/0

私が望むのは、dev/stdinTARファイル内にtextを含む一般的なファイルがあるということですtest。次のような状況でも同様の状況が発生します。

$ tar -cf test.tar <(echo test)

しかし、名前は異なります。

これは可能ですか?

答え1

私の考えでは、ここでやりたいことができないと思います。アプローチの問題は、tarファイルとディレクトリツリーを処理し、次のコマンドを提供しないことです。

$ echo test | tar -cf test.tar /dev/sdtin

次のサブシェルを使用して一時ファイルの文字列を「ラップ」しようとしても、

$ tar -cf test.tar <(echo test)

コンテンツがまだ TAR 圧縮に次の一時ファイル記述子を使用していることを確認できます。

$ tar tvf test.tar
lr-x------ vagrant/vagrant   0 2018-08-04 23:52 dev/fd/63 -> pipe:[102734]

文字列を圧縮したい場合は、ファイルコンテキストに入れる必要があります。したがって、次のようにする必要があります。

$ echo "test" > somefile && tar -cf /tmp/test.tar somefile

TARファイルにそのファイルが存在することを確認できます。

$ tar tvf /tmp/test.tar
-rw-rw-r-- vagrant/vagrant   5 2018-08-05 00:00 somefile

tarを使用したデータのコピー

長い間Unixを使用してきたほとんどの人は、おそらく次のようなパターンを見たことがあります。

$ (cd /; tar cf - .)|(cd /mnt/newroot; tar pxvf -)

私は過去にある場所から別の場所にデータをコピーするためにこれを使用しました。 SSH経由でも使用できます。他の方法については、U&L Q&Aで次のように議論されています。busyboxを使用したルートディレクトリツリーの複製

バックアップ/

ハードドライブ全体をバックアップしたい場合でも、この方法を使用できます。

$ sudo tar -cvpzf backup.tar.gz --exclude=/backup.tar.gz --one-file-system /

引用する

答え2

転送する最終サイズ(バイト)がわかっている場合は、tarファイルをストリームとして生成できます。その後、データストリームの前に最初の512バイトヘッダーを生成し、その後に末尾のパディングを生成する必要があります。tarファイルの種類が異なるため、ファイルの正確なバリエーションによって異なります。次の手順が役に立ちます。

  1. データストリームと同じサイズの穴ファイルの作成

    $ dd if=/dev/zero of=mystream bs=1 count=0 seek=$SIZE

    このmystreamファイルは「ホール」ファイルで、データストリームと$ SIZEサイズが同じように見えますが、実際にはディスク容量を占有しません。

  2. 指定されたサイズのファイルのtarヘッダーを作成するために使用されます。mystream

    $ tar cf - mystream | head -c 512 > header

    脆弱性tarのないファイルを生成するには、最初の512バイトを除いてすべてを削除することが重要です。その後、誤ってコピーされないように穴ファイルを削除します。

    $ rm mystream

  3. 512個のブロックを埋めるパディングテールを作成します。

    $ head -c $((echo "scale=0; 512 - $SIZE % 512" | bc )) > trailer

  4. ヘッダーとトレーラーを含む$ STREAM(サイズ$ SIZE)のタールストリームを作成します。

    $ cat header $STREAM trailer

    これを標準出力以外の場所にストリーミングすることもできます。

答え3

を使用すると、パイプの代わりに一時ファイルを使用するプロセス代替形式をzsh使用できます。 GNUオプションを=(...)使用すると、アーカイブメンバーの名前を変更できます。tar--transform

tar --transform='s/.*/test-file/' -zcf file.tar.gz =(echo test)

0600権限とcontent権限を持つメンバーをfile.tar.gz作成します。test-filetest\n

bash(または)を使用して、zsh次のことができます。

tar --transform='s/.*/test-file/' -zchf file.tar.gz /dev/stdin <<< "$(echo test)"

Here-stringsはこれらのシェルでも一時ファイルを使用します。ただし、コマンド置換は削除されることに注意してください。すべて末尾の改行と追加一つ戻るとbashNULバイトストリップにあります。

関連情報