Tại sao không phải tất cả các tệp được nén và cách cải thiện giải pháp


8

Tôi có một thư mục với khoảng 20K tệp. Các tập tin được đặt tên theo mẫu xy_{\d1,5}_{\d4}\.abc, ví dụ xy_12345_1234.abc. Tôi muốn nén 10K đầu tiên trong số họ bằng lệnh này:

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

tuy nhiên tệp kết quả chỉ có khoảng 2K tệp bên trong.

ls | sort -n -k1.4,1.9 | head -n10000 | wc -l tuy nhiên trả về 10000, như mong đợi.

Dường như với tôi rằng tôi đang hiểu nhầm một cái gì đó cơ bản ở đây ...

Tôi đang sử dụng zsh 5.0.2 trên Linux Mint 17.1, GNU tar 1.27.1

BIÊN TẬP:

việc giả mạo như được đề xuất bởi @Archemar nghe có vẻ rất hợp lý, với ngã ba mới nhất ghi đè lên tệp kết quả - tệp chứa 'đuôi' của các tệp - 7773 đến 9999 .

kết quả của 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

thay thế -cbằng -rhoặc -ukhông hoạt động trong trường hợp của tôi. Thông báo lỗi làtar: Cannot update compressed archives

sử dụng cả hai -r-ukhông hợp lệ và không thành công vớitar: You may not specify more than one '-Acdtrux', '--delete' or '--test-label' option

thay thế -cbằng -adường như cũng không hợp lệ và thất bại với điều tương tự tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' optionsmặc dù tôi không nhận ra vấn đề azfAcdtruxdường như không phù hợp với tôi.

EDIT 2:

-T có vẻ là một cách tốt, tôi cũng đã tìm thấy một ví dụ ở đây .

Tuy nhiên khi tôi cố gắng

ls | sort -n -k1.4,1.9 | head -n10000 | tar -czf xy_0_10000.tar.gz -T - tôi có tar: option requires an argument -- 'T'

tốt, có lẽ tên tập tin không đạt tar? Nhưng có vẻ như họ, làm bởi vì khi tôi thực thi

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

Vậy tại sao tar không nhìn thấy tên tập tin?


và nếu bạn thử một thay vì c, trong lệnh tar?
Olivier Dulac


1
Tập tin của OP không có tên khó.
Archemar

@ 8bittree - cũng như một lời khuyên chung cho các kịch bản shell mạnh mẽ, vâng. nhưng bạn đề nghị gì thay vì làm việc với danh sách các tệp với các oneliners một lần thông thường?
kostja

1
@kostja Tôi sẽ sử dụng find, có -print0tùy chọn sử dụng byte null làm dấu phân cách thay vì dòng mới. sortcó thể xử lý điều đó với -zcờ. head, thật không may, không xử lý hiểu các dấu phân cách byte null, nhưng câu trả lời này có một giải pháp sử dụng trđể trao đổi \n\0trước và sau head. tar--null -T -đọc rỗng phân định tên tập tin từ stdin.
8

Câu trả lời:


12

bạn đã đạt giới hạn xargs chưa?

xargs --show-limit

thử :

  • tạo một .tgztập tin giảtar czf xy_0_10000.tar.gz /hello/world
  • thay thế -czfbằng -Azf

Khi xarg đạt đến giới hạn của nó, nó sẽ ra lệnh fork, vì vậy lệnh bạn chạy tối đa là

  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

vì mỗi tar nằm trên cái trước, bạn chỉ nên tar cchạy lần cuối .

Biên tập:

1) theo man tarunbfox -avà -r dường như việc nối thêm được thực hiện bởi (một trong hai) -A, --catenate, --concatenate

2) zip(không gzip) có thể được sử dụng để thêm tệp, có thể tùy chọn gzip sẽ thực hiện thủ thuật. (sử dụng | xargs zip -qr xy_0_0000.zip, điều này sẽ dẫn đến một tệp zip, tuy nhiên không phải là .tar.gz)

3) sử dụng giải pháp của @ rsanchez
Điều quan trọng là thêm tùy chọn vào tar theo cách thích hợp, hãy thử

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

trong đó - -T -có nghĩa là tùy chọn sử dụng -Tvà sử dụng -làm đối số cho -T(bạn có thể tạo danh sách tệp trong /tmp/foo.lstđó, sau đó sử dụng -T /tmp/foo.lst)


một (= add) thay vì c (= tạo / ghi đè) có thể làm việc xung quanh giới hạn đó không?
Olivier Dulac

@OlivierDulac ( Cảnh báo: Đây là một phỏng đoán thuần túy ) Có lẽ sẽ không giải quyết được vì tar không thể tạo các tệp trống. Bạn có thể nén một thư mục trống trước và sử dụng a (add)để thêm các tệp vào tệp tar. Sau đó, bạn có thể mở tar và xóa thư mục (sử dụng 7zip hoặc thứ gì đó)
Ismael Miguel

@ismaelmiguel: Tôi khá chắc chắn rằng nó sẽ vui vẻ tạo tập tin. nếu không, chỉ cần:touch xy_0_10000.tar.gz && { _the full command here_ ; }
Olivier Dulac

1
@OlivierDulac Đó sẽ là một .gztệp không hợp lệ .
Ismael Miguel

Tất cả các trang mà tôi thấy từ manpages.ubfox.com/manpages/vivid/en/man1/tar.1.html (15.04) trở lại chính xác (12.04) đều có -rthêm nhưng -atự động nén không tương đương. Và -rzkhông hoạt động: zipcó thể thêm vào một kho lưu trữ hiện có vì thư mục không được nén, nhưng tarvới nén sẽ nén các metatdata cùng với dữ liệu. Bạn có thể tar -rchia thành một kho lưu trữ không nén và sau đó gzip kết quả. Hoặc ...
dave_thndry_085

12

Không cần xargs. Nếu bạn trực tiếp đưa ra tarcác -T -tùy chọn nó sẽ đọc tên tập tin từ đầu vào tiêu chuẩn.

Ví dụ:

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

Tôi dường như đang sử dụng tùy chọn không chính xác, không thể làm cho nó hoạt động với đường ống. Có cố gắng ...| tar Tczf xy_..., ...| tar Tcz -f xy_... ...| tar -czf xy_... -T và một số hoán vị khác, nhưng tôi chỉ nhận được tar: You must specify one of the '-Acdtrux', '--delete' or '--test-label' options, tar: -f: Cannot stat: No such file or directorynếu sử dụng -friêng rẽ với tùy chọn khác và tar: option requires an argument -- 'T'. Bạn có thể vui lòng thêm một ví dụ sử dụng?
kostja

@kostja ví dụ thêm.
rsanchez

Rất cám ơn, rsanchez. Không chắc chắn tại sao biến thể -T -ở cuối tardanh sách tùy chọn không hoạt động, nhưng ví dụ của bạn đã làm. Thật không may, câu hỏi của tôi thực sự có hai phần - nguồn gốc của lỗi và một sự cải thiện có thể. Trong khi bạn đạt được cái sau, Archemar đã xuất sắc ở cái trước và gần như có quyền sau. Tôi không chắc câu trả lời nào của bạn để chấp nhận vì cả hai đều rõ ràng hữu ích.
kostja

1

Tôi muốn bổ sung hai câu trả lời khác bằng một giải pháp zsh , không phân tích cú pháp ls , cũng không cần xargs . Tuy nhiên, tôi không chắc chắn ngay bây giờ, nếu nó cũng bị giới hạn về độ dài của dòng lệnh.

  1. Xác định chức năng tạo khóa sắp xếp mong muốn của bạn bằng cách sửa đổi $REPLY.

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

    Điều này tương đương với sort -n -k1.4,1.9

  2. Tạo một mảng $filesvới tên tệp được sắp xếp với chức năng trên:

    files=(*(o+sortkey))

    Điều này tương đương với ls | sort -n -k1.4,1.9

  3. Trả lại 10 000 tệp đầu tiên với

    ${files[0,9999]}

    Điều này tương đương với ls | sort -n -k1.4,1.9 | head -n10000

Vì vậy, tất cả trong tất cả điều này nên làm thủ thuật:

sortkey() { REPLY=${REPLY[4,9]} }
files=(*(o+sortkey))
tar -czf xy_0_10000.tar.gz ${files[0,9999]}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.