tar: thêm tất cả các tệp và thư mục trong thư mục hiện tại BAO GỒM .svn, v.v.


89

Tôi cố gắng truy cập vào tar.gz một thư mục và sử dụng

tar -czf workspace.tar.gz *

Tar kết quả bao gồm các .svnthư mục trong các thứ tự con nhưng KHÔNG có trong thư mục hiện tại (vì *được mở rộng thành chỉ các tệp 'hiển thị' trước khi nó được chuyển đến tar

Tôi đã cố gắng

tar -czf workspace.tar.gz .thay vào đó, nhưng sau đó tôi gặp lỗi bởi vì '.' đã thay đổi trong khi đọc:

tar: ./workspace.tar.gz: file changed as we read it

Có thủ thuật nào để *khớp với tất cả các tệp (bao gồm cả tiền tố dấu chấm) trong một thư mục không?

(sử dụng bash trên Linux SLES-11 (2.6.27.19)


5
Có lẽ câu hỏi này thuộc về superuser?
Peter Jaric

Câu trả lời:


75

Không tạo tệp tar trong thư mục bạn đang đóng gói:

tar -czf /tmp/workspace.tar.gz .

thực hiện thủ thuật, ngoại trừ nó sẽ giải nén các tệp trong thư mục hiện tại khi bạn giải nén. Tốt hơn nên làm:

cd ..
tar -czf workspace.tar.gz workspace

hoặc nếu bạn không biết tên của thư mục bạn đang ở:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(Điều này giả định rằng bạn đã không theo dõi các liên kết tượng trưng để đến được vị trí của mình và trình bao không cố gắng đoán bạn lần thứ hai bằng cách nhảy ngược lại thông qua một liên kết tượng trưng - bashkhông đáng tin cậy về mặt này. Nếu bạn phải lo lắng về điều đó, sử dụng cd -P ..để thực hiện một thư mục thay đổi vật lý. Thật ngu ngốc rằng đó không phải là hành vi mặc định theo quan điểm của tôi - ít nhất là gây nhầm lẫn cho những người cd ..chưa bao giờ có bất kỳ ý nghĩa thay thế nào.)


Một bình luận trong cuộc thảo luận nói:

Tôi [...] cần loại trừ thư mục trên cùng và tôi [...] cần đặt tar vào thư mục cơ sở.

Phần đầu tiên của nhận xét không có nhiều ý nghĩa - nếu tệp tar chứa thư mục hiện tại, nó sẽ không được tạo khi bạn giải nén tệp từ kho lưu trữ đó bởi vì, theo định nghĩa, thư mục hiện tại đã tồn tại (trừ những trường hợp rất kỳ lạ ).

Phần thứ hai của nhận xét có thể được xử lý theo một trong hai cách:

  1. Hoặc: tạo tệp ở một nơi khác - /tmplà một trong những vị trí khả thi - và sau đó di chuyển nó trở lại vị trí ban đầu sau khi hoàn tất.
  2. Hoặc: nếu bạn đang sử dụng GNU Tar, hãy sử dụng --exclude=workspace.tar.gztùy chọn. Chuỗi sau dấu =là một mẫu - ví dụ là mẫu đơn giản nhất - một khớp chính xác. Bạn có thể cần phải xác định --exclude=./workspace.tar.gzxem bạn có đang làm việc trong thư mục hiện tại trái với các khuyến nghị hay không; bạn có thể cần xác định --exclude=workspace/workspace.tar.gzxem bạn có đang tăng một cấp độ như được đề xuất hay không. Nếu bạn có nhiều tệp tar cần loại trừ, hãy sử dụng ' *', như trong --exclude=./*.gz.

1
Câu trả lời hay nhưng tôi đã gặp một tình huống buộc phải chạy lệnh này bên trong thư mục phải được đóng gói. Tôi có quyền không chính thức để chạy nó bên ngoài.
Hexodus

Một nơi hoàn hảo để đóng gói là / tmp chắc chắn.
Andre Fellows

45

Nếu bạn thực sự không muốn đưa thư mục hàng đầu vào tarball (và đó là ý tưởng tồi):

tar czf workspace.tar.gz -C /path/to/workspace .

Tôi cần loại trừ thư mục trên cùng và tôi cần đặt tar vào thư mục cơ sở.
Micha

@Micha tạo ra một kịch bản bash để lưu trữ và sao chép các tập tin sau
Fedir RYKHTIK

2
Bạn đang thiếu - trong -czf tôi nghĩ.
UpTheCreek,

10
man tar: Đối số đầu tiên của tar phải là một hàm; một trong các chữ cái Acdrtuxhoặc một trong các tên hàm dài. Một ký tự chức năng không cần phải có tiền tố- và có thể được kết hợp với các tùy chọn ký tự đơn khác.
rkhayrov

4
Vẫn không hoạt động, tôi vẫn có dấu "." là thư mục hàng đầu trong tarball của tôi
A. Gille

43

Có một số bước cần thực hiện:

  1. Thay thế *bằng .để bao gồm các tệp ẩn.
  2. Để tạo kho lưu trữ trong cùng một thư mục, --exclude=workspace.tar.gzcó thể sử dụng a để loại trừ chính kho lưu trữ đó.
  3. Để tránh tar: .: file changed as we read itlỗi khi tệp lưu trữ chưa được tạo, hãy đảm bảo rằng tệp đó tồn tại (ví dụ: sử dụng touch), do đó --exclude khớp với tên tệp lưu trữ. (Nó không khớp với nó, tệp không tồn tại)

Kết hợp điều này dẫn đến tập lệnh sau:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
Tôi đọc tất cả các câu trả lời và nhận xét và đây là cách tốt nhất để tạo tarball trong cùng một dir. Từ câu trả lời này, tôi cũng đã hiểu tại sao lỗi này xảy ra.
Szymon Sadło

Nếu bạn muốn nhìn thấy sự tiến bộ trong khi nó đang nén tập tin tar, bạn có thể thêm một lá cờ bổ sung cho --verbose, như vậy: -czvf.
Mastrianni

18

trong thư mục muốn nén (thư mục hiện tại) hãy thử điều này:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
Nhưng bây giờ nó phàn nàn rằng tệp "." đã thay đổi khi đang đọc. Tôi có thể chắc chắn rằng tất cả các tệp đã được bao gồm không?
Jaan

1
Điều này loại trừ tất cả .gzcác tệp trong thư mục.
omerfarukdogan

12

Bạn có thể bao gồm các thư mục ẩn bằng cách quay lại một thư mục và thực hiện:

cd ..
tar czf workspace.tar.gz workspace

Giả sử thư mục bạn muốn gzip được gọi là không gian làm việc.


Và điều này cũng tránh được sự cố thay đổi tệp.
Jonathan Leffler

Không hoạt động khi người dùng không có quyền ghi trong thư mục mẹ.
Joachim Wagner

Chính xác là @JoachimWagner!
p01ymath

1
@JoachimWagner. Nếu bạn không có quyền ghi, thay đổi nó để được:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Tôi đã phải lấy ra -trước khi czflàm cho nó hoạt động. Nếu không, tôi đã nhận được Cannot stat: No such file or directorythông báo lỗi.
Phemelo Khetho

6

Bạn có thể sửa .biểu mẫu bằng cách sử dụng --exclude:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

Cập nhật: Tôi đã thêm một bản sửa lỗi cho nhận xét của OP.

tar -czf workspace.tar.gz .

thực sự sẽ thay đổi thư mục hiện tại, nhưng tại sao không đặt tệp ở một nơi khác?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

Các tập tin sẽ được xử lý sau đó và bắt buộc phải trong không gian làm việc - đó là một chút thầu xấu xí nhưng nó chỉ là cần thiết (điều toàn bộ ist chỉ là một cách giải quyết ...)
Micha

OK, tôi sẽ thêm một bản sửa lỗi cho điều đó :)
Peter Jaric

Và nếu bạn cần có thể chạy điều này nhiều lần, hãy thêm 'rm workspace.tar.gz' trước dòng tar.
Peter Jaric

Nếu bạn muốn tar toàn bộ một ổ đĩa, vào cùng một ổ đĩa đó, có vẻ như bạn không có nhiều lựa chọn.
BeeOnRope,

4

Trên thực tế, vấn đề là với các tùy chọn nén. Bí quyết là đưa kết quả hắc ín đến máy nén thay vì sử dụng các tùy chọn tích hợp sẵn. Ngẫu nhiên điều đó cũng có thể cung cấp cho bạn khả năng nén tốt hơn, vì bạn có thể đặt các tùy chọn nén bổ sung.

Hắc ín tối thiểu:

tar --exclude=*.tar* -cf workspace.tar .

Đường ống đến máy nén do bạn lựa chọn. Ví dụ này dài dòng và sử dụng xz với độ nén tối đa:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

Giải pháp đã được thử nghiệm trên Ubuntu 14.04 và Cygwin trên Windows 7. Đây là câu trả lời của wiki cộng đồng, vì vậy hãy thoải mái chỉnh sửa nếu bạn phát hiện ra sai sót.


Cảm ơn bạn! Cuộc sống ma đã được cứu
Steven

2

Vấn đề với hầu hết các giải pháp được cung cấp ở đây là hắc ín luôn tồn ./tại ở mọi mục nhập. Vì vậy, điều này dẫn đến việc có .thư mục khi mở nó thông qua máy nén GUI. Vì vậy, những gì tôi đã làm là:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

Nếu bạn đã có my.tar.gztrong thư mục hiện tại, bạn có thể muốn loại bỏ điều này:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

Cần biết rằng xargs có giới hạn nhất định (xem xargs --show-limits). Vì vậy, giải pháp này sẽ không hoạt động nếu bạn đang cố gắng tạo một gói có nhiều mục nhập (thư mục và tệp) trên một thư mục mà bạn đang cố gắng tar.


1

Một câu hỏi hay. Trong ZSH, bạn có thể sử dụng công cụ sửa đổi hình cầu (D), viết tắt của "dotfiles". So sánh:

ls $HOME/*

ls $HOME/*(D)

Điều này chính xác loại trừ các mục nhập thư mục đặc biệt .... Trong Bash, bạn có thể sử dụng .*để bao gồm các tệp dotfiles một cách rõ ràng:

ls $HOME/* $HOME/.*

Nhưng điều đó cũng bao gồm ...cả, vì vậy nó không phải là những gì bạn đang tìm kiếm. Tôi chắc rằng cũng có một số cách để tạo các *tệp chấm đối sánh trong bash.


Trong bash, sử dụng .??*để khớp với tất cả các tệp chấm không .... Điều đó không nhận được các tệp chấm ký tự đơn (như .a). Để có được những thứ đó, hãy sử dụng cái phức tạp hơn .[^.]*.
Scott Minster

1

Tuy nhiên, một giải pháp khác, giả sử số lượng mục trong thư mục không lớn:

tar -czf workspace.tar.gz `ls -A`

( ls -Ain các tệp bình thường và ẩn nhưng không in "." và ".." như ls -avậy.)


0
tar -czf workspace.tar.gz .??* *

Việc chỉ định .??*sẽ bao gồm các tệp và thư mục "chấm" có ít nhất 2 ký tự sau dấu chấm. Mặt trái của nó là nó sẽ không bao gồm các tệp / thư mục có một ký tự sau dấu chấm, chẳng hạn như .anếu có.


0

Nếu dung lượng ổ đĩa không phải là một vấn đề, đây cũng có thể là một điều rất dễ thực hiện:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

Bản thân tôi cũng gặp tình huống tương tự. Tôi nghĩ tốt nhất là tạo tar ở nơi khác và sau đó sử dụng -C để cho tar thư mục cơ sở cho các tệp nén. Thí dụ:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

Bằng cách này không cần loại trừ tệp tarfile của riêng bạn. Như đã lưu ý trong các nhận xét khác, -A sẽ liệt kê các tệp ẩn.


0

10 năm sau, bạn có một giải pháp thay thế tar, được minh họa bằng Git 2.30 (Q1 2021), sử dụng " git archive" ( người đàn ông ) để sản xuất tarball phát hành thay vì tar.
(Bạn không cần Git 2.30 để áp dụng giải pháp thay thế đó)

Xem cam kết 4813277 (11 tháng 10 năm 2020) và cam kết 93e7031 (10 tháng 10 năm 2020) bởi René Scharfe ( rscharfe) .
(Được hợp nhất bởi Junio ​​C Hamano - gitster- trong cam kết 63e5273 , ngày 27 tháng 10 năm 2020)

Makefile: sử dụng git init / add / commit / archive cho dist-doc

Ký tên: René Scharfe

Giảm sự phụ thuộc vào các công cụ bên ngoài bằng cách tạo các kho lưu trữ phân phối cho tài liệu HTML và các trang sử dụng lệnh ( man ) thay vì tar. Điều này cung cấp cho các mục nhập kho lưu trữ cùng một dữ liệu meta như những dữ liệu trong kho lưu trữ dist cho tệp nhị phân.git

Vì vậy, thay vì:

tar cf ../archive.tar .

Bạn chỉ có thể thực hiện bằng Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

Điều đó ban đầu được đề xuất bởi vì, như đã giải thích ở đây , một số nền tảng kỳ lạ có thể có một bản phân phối tar cũ với các tùy chọn thiếu.


-1

Sử dụng findcó lẽ là cách dễ nhất:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1sẽ tìm thấy tất cả các tệp / thư mục / symlinks / etc trong thư mục hiện tại và chạy lệnh được chỉ định bởi -exec. Trong {}lệnh có nghĩa là danh sách tệp ở đây\+có nghĩa là lệnh sẽ được chạy dưới dạng:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

thay vì

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J là --xz trong sách hướng dẫn; kết hợp với -c chỉ là sự khởi đầu của cái mà máy tính sẽ gọi là "vui vẻ" :)
Ricalsin

Haha, máy chủ mini của tôi ở nhà bị giới hạn bởi không gian đĩa hơn là CPU :) Mặc dù vậy, điểm tốt; Tôi sẽ thay đổi nó để sử dụng gzip.
Andrew Gunnerson,
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.