すべてのファイルが圧縮されていない理由とソリューションの改善方法


8

約20Kファイルのフォルダがあります。ファイルは、パターンに従って命名されているxy_{\d1,5}_{\d4}\.abc、例えばxy_12345_1234.abc。次のコマンドを使用して、最初の10Kを圧縮したいと思います。

ls | sort -n -k1.4,1.9 | head -n10000 | xargs tar -czf xy_0_10000.tar.gz

ただし、結果のファイルには約2Kのファイルしかありませんでした。

ls | sort -n -k1.4,1.9 | head -n10000 | wc -l ただし、期待どおりに10000を返します。

ここで基本的なことを誤解しているようです...

Linux Mint 17.1、GNU tar 1.27.1でzsh 5.0.2を使用しています

編集:

@Archemarによって提案されたフォークは非常にもっともらしいように聞こえ、最新のフォークが結果のファイルを上書きします-ファイルにはファイルの「テール」が含まれています-7773から9999

の結果xargs --show-limit Your environment variables take up 3973 bytes POSIX upper limit on argument length (this system): 2091131 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2087158 Size of command buffer we are actually using: 131072

交換-cして-rか、-u私の場合には動作しませんでした。エラーメッセージはtar: Cannot update compressed archives

両方-rを使用すると-u無効になり、失敗しますtar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option

との置き換えも無効-cである-aように見え、同じtar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' optionsように失敗しますが、問題azfを認識Acdtruxしていないため、私には矛盾しているようです。

編集2:

-Tは良い方法のように見えますここでも例を見つけました。

しかし私がしようとすると

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - 私は得る tar: option requires an argument -- 'T'

まあ、おそらくファイル名はtarに達しませんか?しかし、それは彼らのように見えます、私が実行すると

ls | sort -n -k1.4,1.9 | head -n10000 | tar --null -czf xy_0_10000.tar.gz -T - 私は得る tar: xy_0_.ab\nxy_1_...<the rest of filenames separated by literal \n>...998.ab Cannot stat: File name too long

では、なぜtarがファイル名を表示しないのですか?


そして、あなたがcの代わりにaを試した場合、tarコマンドで?
Olivier Dulac


1
OPのファイルにはトリッキーな名前がありません。
Archemar

@ 8bittree-確かに、堅牢なシェルスクリプトに関する一般的なアドバイスです。しかし、通常の1回限りのワンライナーでファイルのリストを操作する代わりに何を提案しますか?
kostja

1
@kostja私が使用したいfind持っている、-print0代わりに改行の区切り文字としてnullバイトを使用するオプションを。フラグでsortそれを処理でき-zます。head、残念ながらnullバイト区切り文字の処理を処理していませんが、この回答にtrswap \n\0beforeとafter を使用するソリューションがありますheadtar持っている--null -T -からヌル区切りのファイル名を読み取ることstdin
8ビットツリー、2015

回答:


12

xargs制限に達しましたか?

xargs --show-limit

試してください:

  • ダミー.tgzファイルを作成するtar czf xy_0_10000.tar.gz /hello/world
  • 置き換える-czfことにより、 -Azf

xargが制限に達すると、コマンドがforkされるため、最後に実行したコマンドは

  tar czf xy_0_10000.tar.gz file1 file2 .... file666
  tar czf xy_0_10000.tar.gz file667 file668 ... file1203
  tar czf xy_0_10000.tar.gz file1024 ... file2000

各tarが前のtarを上書きするので、最後のtar c実行のみを取得することになります。

編集:

1)onbuntuによると、-rは同等のman tar-a追加が(どちらか)によって行われて いるようです-A, --catenate, --concatenate

2)zip(ではないgzip)を使用してファイルを追加できます。おそらくgzipオプションでうまくいくでしょう。( | xargs zip -qr xy_0_0000.zipただし、これは.tar.gzではなくzipファイルになります)

3)@rsanchezのソリューションを使用
するtarに適切な方法でオプションを追加することが重要です。

ls | sort -n -k1.4,1.9 | head -n10000 |tar -czf xy_0_10000.tar.gz -T -

ここで- -T -オプション-Tを使用し-、引数として使用することを意味します-T(でファイルのリストを生成してから/tmp/foo.lst、を使用できます-T /tmp/foo.lst


c(=作成/上書き)の代わりに(=追加)でその制限を回避できますか?
Olivier Dulac

@OlivierDulac(警告:これは純粋な推測です)tarは空のファイルを作成できないため、おそらく解決しません。あなたはあり最初の空のフォルダを圧縮して使用a (add)tarファイルにファイルを追加します。次に、タールを開いてフォルダーを削除できます(7zipなどを使用)
Ismael Miguel

@ismaelmiguel:きっと喜んでファイルが作成されると思います。ない場合は、単に:touch xy_0_10000.tar.gz && { _the full command here_ ; }
オリヴィエ・デュラック

1
@OlivierDulacそれは無効な.gzファイルになります。
Ismael Miguel

私から見る全てのmanページmanpages.ubuntu.com/manpages/vivid/en/man1/tar.1.html正確に(15.04)バック(12.04)が持っている-rアペンドが、-a同じではありません自動圧縮を。また、-rz機能しません。zipディレクトリは圧縮されていないため、既存のアーカイブに追加できますがtar、圧縮を使用すると、メタデータがデータとともに圧縮されます。あなたは可能tar -rに区分的非圧縮アーカイブして、その結果をgzip。または...
dave_thompson_085

12

の必要はありませんxargs。あなたが直接与えた場合のオプションをそれがされますファイル名を読んで、標準入力から。tar-T -

例えば:

... | tar -T - -czf xy_0_10000.tar.gz

オプションを間違って使用しているようですが、パイプで機能させることができません。持ってはみました...| tar Tczf xy_......| tar Tcz -f xy_... ...| tar -czf xy_... -T および他のいくつかの順列が、唯一取得していますtar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' optionstar: -f: Cannot stat: No such file or directory使用している場合-f、他のオプションとは別にtar: option requires an argument -- 'T'。使用例を追加していただけませんか?
kostja

@kostjaの例が追加されました。
rsanchez 2015

どうもありがとう、rsanchez。オプションリストの-T -最後にがあるバリアントが機能しなかった理由はわかりませんtarが、例では機能しました。残念ながら、私の質問には実際には2つの部分がありました-エラーの原因と改善の可能性です。あなたが後者に勝った間、Archemarは前者に優れ、ほとんど後者の権利を持っていました。どちらも明らかに役に立ったので、どちらの回答を受け入れるかはわかりません。
kostja

1

lsを解析せず、xargsも必要としないzshソリューションで他の2つの答えを補完したいと思います。ただし、コマンドラインの長さの制限もあるかどうかは、現時点ではわかりません。

  1. を変更して、目的の並べ替えキーを生成する関数を定義します$REPLY

    sortkey() { REPLY=${REPLY[4,9]} }

    これはあなたと同等です sort -n -k1.4,1.9

  2. $files上記の関数でソートされたファイル名で配列を生成します。

    files=(*(o+sortkey))

    これは ls | sort -n -k1.4,1.9

  3. 最初の10 000ファイルを返す

    ${files[0,9999]}

    これは ls | sort -n -k1.4,1.9 | head -n10000

だから、すべてこれでトリックをする必要があります:

sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.