web-dev-qa-db-ja.com

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

約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 Mint17.1でzsh5.0.2を使用していますGNU tar 1.27.1

編集:

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

_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_で失敗しますが、問題azfAcdtruxは論理和のようです。私。

編集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がファイル名を認識しないのはなぜですか?

8
kostja

xargsは必要ありません。 tar-T -オプションを直接指定すると、標準入力から ファイル名を読み取る になります。

例えば:

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

xargsの制限に達しましたか?

_xargs --show-limit
_

試してみてください:

  • ダミーの_.tgz_ファイルを作成する_tar czf xy_0_10000.tar.gz /hello/world_
  • _-czf_を_-Azf_に置き換えます

xargが限界に達すると、コマンドがフォークされるため、最終的に実行したコマンドは

_  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 c_の実行のみを取得する必要があります。

編集:

1) unbuntuの_man tar_によると、_-a_と-rは同等のようです 追加は(どちらか)によって行われます_-A, --catenate, --concatenate_

2)Zipgzipではない)を使用してファイルを追加できます。おそらく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_)

12
Archemar

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

  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. 最初の10000ファイルを

    ${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]}
1
mpy