chỉ các tập tin tar, không có thư mục


16

Tôi có thể chỉ có thể viết một tập lệnh shell để tìm các tệp, sau đó chuyển danh sách sang tar, nhưng tôi tự hỏi liệu đã có một tính năng tích hợp trong tar cho phép thực hiện điều đó chưa, trong một dòng lệnh?

Ví dụ: tôi đã tìm thấy công --no-recursiontắc, nhưng khi tôi làm:

tar --no-recursion -cvf mydir.tar mydir

Nó chỉ lưu trữ tên của các mục trong thư mục (bao gồm cả thư mục con!), Nhưng nó không lưu trữ bất kỳ tệp nào.

Tôi cũng đã thử:

 tar --no-recursion -cvf mydir.tar mydir/*

Nhưng trong khi nó chỉ lưu trữ các tệp, nó cũng lưu trữ tên của các thư mục con.

Có cách nào để chỉ nói với các tập tin tar, không có thư mục?


5
Chỉ cần làm rõ: bạn có muốn tạo một kho lưu trữ với cấu trúc "phẳng" (tức là tất cả các tệp được trộn lẫn trong một thư mục) không?
rozcietrzewiacz

1
Bạn có thể tạo một thư mục mới find mydir -type f |xargs cp -t tempdirvà sau đó tar tempdir.
Kevin

@rozcietrzewiacz Có, căn hộ, nhưng chỉ từ thư mục đó, không phải từ thư mục con.
ateiob

1
OK, tôi nghĩ rằng tôi thấy những gì bạn đang cố gắng làm. Làm thế nào vềfind mydir -depth 1 -type f | xargs tar cf mydir.tar
Kevin

2
À, không gian. Sử dụng find -exec thay thế : find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +. Việc +đặt tất cả các tệp trên cùng một dòng lệnh như xargs.
Kevin

Câu trả lời:


11

Như camh chỉ ra, lệnh trước có một vấn đề nhỏ trong đó có quá nhiều tên tệp, nó sẽ thực thi nhiều lần, với các lệnh sau này âm thầm xóa sạch các lần chạy trước đó. Vì chúng tôi cũng không nén, chúng tôi có thể nối thêm thay vì ghi đè:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar Avf mydir.tar
find mydir -maxdepth 1 -type f -exec tar Avf mydir.tar {} +

Câu trả lời Iocnarz của của việc sử dụng tar's --null-Tlựa chọn các công trình là tốt. Nếu bạn đã cpiocài đặt, câu trả lời của camh sử dụng nó cũng tốt. Và nếu bạn có zshvà không phiền khi sử dụng nó cho một lệnh, câu trả lời của Gilles bằng cách sử dụng zsh global ( *(.)) có vẻ đơn giản nhất.


Chìa khóa là -maxdepthtùy chọn. Câu trả lời cuối cùng, xử lý các không gian thích hợp:

find mydir -maxdepth 1 -type f -print0 | xargs -0 tar cvf mydir.tar

Điều này cũng sẽ làm việc:

find mydir -maxdepth 1 -type f -exec tar cvf mydir.tar {} +

4
Cả hai điều này có thể dẫn đến nhiều lời mời tar. Cả hai xargsfindvới +biến thể có số lượng đối số tối đa có thể được chuyển sang tar. Điều này sẽ dẫn đến việc gọi tar thứ hai ghi đè đầu ra của đầu tiên.
camh

2
Mở rộng về giới hạn xargs, xargs mặc định thành dòng lệnh tối đa 128KiB. Nếu danh sách tệp lớn hơn, bạn nhận được lệnh thứ hai (hoặc nhiều hơn) của lệnh (tar), dẫn đến mất dữ liệu im lặng. Bạn có thể sử dụng -xđể buộc xargs thất bại thay vì mất dữ liệu và tốt hơn là lỗi mất dữ liệu im lặng, điều đó vẫn không lý tưởng. Lỗi sắp xếp này rất nguy hiểm vì ban đầu mọi thứ có vẻ ổn, nhưng khi danh sách tệp phát triển theo thời gian, bạn bắt đầu kích hoạt nó và có thể không nhận thấy cho đến khi bạn cố gắng khôi phục lại bản sao lưu của mình. Vậy thì đã quá muộn.
camh

@camh Bạn nói đúng, cảm ơn vì đã chỉ ra điều đó; Tôi đã cập nhật để phản ánh điều đó.
Kevin

1
"Câu trả lời cuối cùng" là không chính xác, nếu bạn sử dụng "tar c" mà không -T bạn có thể nhận được một phần kết quả.
eckes

14

Khi bạn muốn sử dụng findvới tar, cách tốt nhất là sử dụng cpiothay vì tar. cpiocó thể viết lưu trữ tar và được thiết kế để lấy danh sách các tệp để lưu trữ từ stdin.

find mydir -maxdepth 1 -type f -print0 | cpio -o -H ustar -0 > mydir.tar

Sử dụng findcpiolà một cách tiếp cận unix-y hơn ở chỗ bạn cho phép findthực hiện lựa chọn tệp với tất cả sức mạnh mà nó có, và hãy cpiothực hiện việc lưu trữ. Thật đáng để học cách sử dụng đơn giản này cpio, vì bạn thấy dễ dàng giải quyết các vấn đề mà bạn gặp phải trước khi thử tar.


Xuất sắc! Tôi đã sử dụng cpio trong quá khứ xa xôi, nhưng chưa bao giờ biết đến tùy chọn ustar.
Ian McGowan

2
Điều này làm việc tốt hơn cho tôi nhiều hơn câu trả lời được chấp nhận.
Dale Anderson

1
chỉ là một nit. -maxdepth 1 sẽ xuất hiện trước -type f hoặc bạn sẽ nhận được cảnh báo từ một số kết quả tìm kiếm
kdub

Cảm ơn @kdub. Tôi đã cập nhật câu trả lời để đặt -maxdepthtrước -type.
camh

3

Tôi không chắc tôi hiểu yêu cầu của bạn. Nếu bạn muốn lưu trữ các tệp thông thường trong mydirnhưng không phải các thư mục con của nó, cách dễ nhất là sử dụng zsh, trong đó chỉ khớp các tệp thông thường là vấn đề đơn giản khi sử dụng . vòng loại toàn cầu :

tar cf mydir.tar mydir/*(.)

3

Bạn thậm chí có thể sử dụng find ... -print0tar ... --nulltrực tiếp mà không cần sử dụng xargs.

find . -maxdepth 1 -type f -print0 | tar cvf mydir.tar --null -T -

Trong ví dụ đã cho, --no-recursiontùy chọn tarkhông cần thiết vì chỉ các đường dẫn của tệp (và không phải thư mục) sẽ được truyền từ findđến tar.

Tuy nhiên, sử dụng --no-recursiontùy chọn tartrong ví dụ sau, ngăn chặn các tarthư mục lưu trữ kép. findsẽ làm đệ quy cây thư mục thay vì tarsau đó.

# compare
find . -print0 | tar cf mydir.tar --null -T -
tar -tf mydir.tar | nl

find . -print0 | tar cf mydir.tar --null --no-recursion -T -
tar -tf mydir.tar | nl

2

Như đoạn giới thiệu trong man tarcâu nói (câu cuối),

Việc sử dụng tên thư mục luôn ngụ ý rằng các thư mục con bên dưới phải được đưa vào kho lưu trữ.

Mà tôi hiểu là câu trả lời "không" cho câu hỏi của bạn.


Tốt bắt, ngoại trừ việc tar hiện nay bao gồm nhiều meachisms trừ (ví dụ --no-recursion, --exclude-tagvv). Tôi đang nhìn vào --exclude-tagđó có vẻ đầy hứa hẹn nhưng dường như trái ngược hoàn toàn với những gì tôi đang tìm kiếm.
ateiob

Tôi đã thử điều này và tôi thấy các nhân vật bị xóa khỏi tên đường dẫn dài. Sử dụng tar với -T và --null như camh đề xuất đã tránh được vấn đề này.
Paul Brannan

1
star -c -C startdir -find . ! -type d > out.tar

Bỏ qua -C startdirvà thay thế .bằng startdirnếu nó sẽ xuất hiện trong kho lưu trữ.

Đây là phương pháp hiệu quả nhất dựa trên các tính năng của libfind. Libfind cũng cung cấp các -chown -chgrp -chmodnguyên tắc sửa đổi cấu trúc stat tại chỗ và cho phép lưu trữ các siêu dữ liệu khác nhau. Điều này cũng hoạt động trong chế độ danh sách và trích xuất và tránh sự cần thiết phải trích xuất toàn bộ kho lưu trữ trong nhiều trường hợp.


Bạn có thể sử dụng -findtrong -copychế độ. Bản tóm tắt trang man gợi ý bạn có thể nhưng tôi không thể làm cho nó hoạt động được (trong khi cố gắng trả lời Cách sao chép các tệp đã sửa đổi trong khi bảo quản cấu trúc thư mục ) (với schily-2016 / 02-10)
Stéphane Chazelas

Tôi đã không kiểm tra điều này trong một thời gian dài. Có thể là hiện tại có một lỗi. Trang man nói rằng đối số cuối cùng sẽ là thư mục trích xuất, nhưng khi tôi thử điều này, tôi nhận được: "Đối số đường dẫn chưa được hỗ trợ trong chế độ giải nén". Đây có phải là những gì bạn nhận được khi bạn cố gắng?
schily

Đúng. Trang người đàn ông cũng nói rằng bạn chỉ có thể tìm thấy các đối số sau -find nhưng nếu tôi đặt thư mục đích trước -tìm tôi cũng gặp lỗi
Stéphane Chazelas

Có mã để tắt mã tìm kiếm trong quá trình giải nén và thông báo lỗi là từ một kiểm tra không chính xác mà mong đợi -c nhưng cũng nên cho phép -copy. Trong chế độ -copy, trình phân tích cú pháp tìm không được bao gồm đối số cuối cùng.
schily

1
Một giải pháp cuối cùng hiện đã được công bố trong các công cụ schily tại sourceforge.net/projects/schilytools/files/schily-2016-03-11.tar.bz2 điều này cũng khắc phục sự cố từ một setlocale () bị thiếu trong sao và điều này cho phép - C chỉ đạo cho star -find.
schily

0

Tôi có thể đã tìm thấy một giải pháp.

find mydir -type f -printf '%P\0'|tar czvf mydir.tar.gz -C mydir --null -T -

Điều này có thể tốn kém một chút, nhưng dù sao nó cũng sẽ hoạt động, bởi vì điều này không phụ thuộc vào xargs.


-1

dir = your_dir; cd $ dir; tar -cvf file.tar `tìm. -maxdepth 1 -type f -print`

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.