tar: tambahkan semua file dan direktori di direktori saat ini TERMASUK .svn dan seterusnya


90

Saya mencoba untuk tar.gz direktori dan menggunakan

tar -czf workspace.tar.gz *

Tar yang dihasilkan termasuk .svndirektori dalam subdir tetapi BUKAN di direktori saat ini (karena *diperluas hanya ke file 'terlihat' sebelum diteruskan ke tar

saya mencoba untuk

tar -czf workspace.tar.gz .sebagai gantinya tetapi kemudian saya mendapatkan kesalahan karena '.' telah berubah saat membaca:

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

Apakah ada trik agar *cocok dengan semua file (termasuk dot-prefixed) dalam sebuah direktori?

(menggunakan bash di Linux SLES-11 (2.6.27.19)


5
Mungkin pertanyaan ini milik superuser?
Peter Jaric

Jawaban:


76

Jangan membuat file tar di direktori yang Anda kemas:

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

melakukan trik, kecuali itu akan mengekstrak file di seluruh direktori saat ini ketika Anda membongkar. Lebih baik dilakukan:

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

atau, jika Anda tidak tahu nama direktori tempat Anda berada:

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

(Ini mengasumsikan bahwa Anda tidak mengikuti symlink untuk sampai ke tempat Anda sekarang dan bahwa shell tidak mencoba menebak-nebak Anda dengan melompat ke belakang melalui symlink - bashtidak dapat dipercaya dalam hal ini. Jika Anda harus khawatir tentang itu, gunakan cd -P ..untuk melakukan direktori perubahan fisik. Bodoh bahwa ini bukan perilaku default dalam pandangan saya - membingungkan, setidaknya, bagi mereka yang cd ..tidak pernah memiliki arti alternatif.)


Satu komentar dalam diskusi mengatakan:

Saya [...] perlu mengecualikan direktori teratas dan saya [...] perlu menempatkan tar di direktori dasar.

Bagian pertama dari komentar tidak masuk akal - jika file tar berisi direktori saat ini, itu tidak akan dibuat saat Anda mengekstrak file dari arsip itu karena, menurut definisi, direktori saat ini sudah ada (kecuali dalam keadaan yang sangat aneh ).

Bagian kedua dari komentar dapat ditangani dengan salah satu dari dua cara berikut:

  1. Salah /tmpsatunya : buat file di tempat lain - adalah satu kemungkinan lokasi - lalu pindahkan kembali ke lokasi asli setelah selesai.
  2. Atau: jika Anda menggunakan GNU Tar, gunakan --exclude=workspace.tar.gzopsi. String setelah =adalah pola - contohnya adalah pola yang paling sederhana - pencocokan tepat. Anda mungkin perlu menentukan --exclude=./workspace.tar.gzapakah Anda bekerja di direktori saat ini yang bertentangan dengan rekomendasi; Anda mungkin perlu menentukan --exclude=workspace/workspace.tar.gzapakah Anda mengerjakan satu tingkat seperti yang disarankan. Jika Anda memiliki beberapa file tar untuk dikecualikan, gunakan ' *', seperti pada --exclude=./*.gz.

1
Jawaban bagus tetapi saya mendapat situasi di mana saya terpaksa menjalankan perintah ini di dalam direktori yang harus dikemas. Saya memiliki izin yang tidak memadai untuk menjalankannya di luar.
Hexodus

Tempat yang sempurna untuk mengemas adalah / tmp.
Andre Fellows

46

Jika Anda benar - benar tidak ingin memasukkan direktori teratas ke dalam tarball (dan biasanya itu ide yang buruk):

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

Saya perlu mengecualikan direktori teratas dan saya perlu menempatkan tar di direktori dasar.
Micha

@Micha membuat skrip bash untuk mengarsipkan dan menyalin file setelahnya
Fedir RYKHTIK

2
Anda melewatkan - dalam -czf saya kira.
UpTheCreek

10
man tar: Argumen pertama untuk tar harus berupa fungsi; salah satu huruf Acdrtux, atau salah satu nama fungsi yang panjang. Surat fungsi tidak perlu diawali dengan- , dan dapat digabungkan dengan opsi satu huruf lainnya.
rkhayrov

4
Masih tidak berhasil, saya masih memiliki "." sebagai direktori teratas di tarball saya
A. Gille

43

Ada beberapa langkah yang harus dilakukan:

  1. Ganti *dengan .untuk menyertakan file tersembunyi juga.
  2. Untuk membuat arsip di direktori yang sama, --exclude=workspace.tar.gzdapat digunakan untuk mengecualikan arsip itu sendiri.
  3. Untuk mencegah tar: .: file changed as we read itkesalahan saat arsip belum dibuat, pastikan arsip itu ada (misalnya menggunakan touch), sehingga --exclude cocok dengan nama file arsip. (Tidak cocok jika file tidak ada)

Hasil ini digabungkan dalam skrip berikut:

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

7
Saya membaca semua jawaban dan komentar dan ini adalah cara terbaik untuk membuat tarball di direktori yang sama. Dari jawaban ini saya juga mengerti mengapa kesalahan ini terjadi.
Szymon Sadło

Jika Anda ingin melihat kemajuan sementara itu mengompresi file tar Anda, Anda dapat menambahkan bendera tambahan untuk --verbose, seperti: -czvf.
Mastrianni

18

dalam direktori ingin kompres (direktori saat ini) coba ini:

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

2
Tapi sekarang mengeluh bahwa file "." berubah saat sedang dibaca. Dapatkah saya yakin bahwa semua file telah disertakan?
Jaan

1
Ini mengecualikan semua .gzfile di direktori.
omerfarukdogan

12

Anda dapat memasukkan direktori tersembunyi dengan kembali ke direktori dan melakukan:

cd ..
tar czf workspace.tar.gz workspace

Dengan asumsi direktori yang ingin Anda gzip bernama workspace.


Dan ini juga untuk menghindari masalah pengubahan file.
Jonathan Leffler

Tidak berfungsi saat pengguna tidak memiliki izin menulis di folder induk.
Joachim Wagner

Persis @JoachimWagner!
p01ymath

1
@Tokopedia Jika Anda tidak memiliki izin menulis, ubahlah menjadi:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
Saya harus mengambil -sebelum czfmembuatnya bekerja. Jika tidak, saya mendapatkan Cannot stat: No such file or directorypesan kesalahan.
Phemelo Khetho

6

Anda dapat memperbaiki .formulir dengan menggunakan --exclude:

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

5

Pembaruan: Saya menambahkan perbaikan untuk komentar OP.

tar -czf workspace.tar.gz .

memang akan mengubah direktori saat ini, tetapi mengapa tidak menempatkan file di tempat lain?

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

File tersebut akan diproses setelahnya dan harus ada di ruang kerja - ini sedikit tawaran yang buruk tetapi hanya diperlukan (semuanya hanyalah solusi ...)
Micha

Oke, saya akan menambahkan perbaikan untuk itu :)
Peter Jaric

Dan jika Anda perlu menjalankan ini berulang kali, tambahkan 'rm workspace.tar.gz' sebelum baris tar.
Peter Jaric

Jika Anda ingin memasukkan seluruh drive ke dalam drive yang sama, tampaknya Anda tidak memiliki banyak pilihan.
BeeOnRope

4

Sebenarnya masalahnya ada pada opsi kompresi. Triknya adalah menyalurkan hasil tar ke kompresor alih-alih menggunakan opsi bawaan. Kebetulan itu juga dapat memberi Anda kompresi yang lebih baik, karena Anda dapat menyetel opsi kompresi tambahan.

Tar minimal:

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

Gunakan pipa ke kompresor pilihan Anda. Contoh ini verbose dan menggunakan xz dengan kompresi maksimum:

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

Solusi telah diuji pada Ubuntu 14.04 dan Cygwin pada Windows 7. Ini adalah jawaban wiki komunitas, jadi silakan mengedit jika Anda melihat kesalahan.


Terima kasih! Menyelamatkan nyawa saya
Steven

2

Masalah dengan sebagian besar solusi yang disediakan di sini adalah tar berisi ./permintaan setiap entri. Jadi ini menghasilkan .direktori saat membukanya melalui kompresor GUI. Jadi yang akhirnya saya lakukan adalah:

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

Jika Anda sudah memiliki my.tar.gzdirektori saat ini, Anda mungkin ingin menghapus ini:

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

Sadarilah bahwa xargs memiliki batas tertentu (lihat xargs --show-limits). Jadi solusi ini tidak akan berhasil jika Anda mencoba membuat paket yang memiliki banyak entri (direktori dan file) pada direktori yang Anda coba tar.


1

Pertanyaan yang bagus. Di ZSH Anda dapat menggunakan pengubah globbing (D), yang merupakan singkatan dari "dotfiles". Membandingkan:

ls $HOME/*

dan

ls $HOME/*(D)

Ini dengan benar mengecualikan entri direktori khusus .dan ... Di Bash Anda dapat menggunakan .*untuk menyertakan dotfiles secara eksplisit:

ls $HOME/* $HOME/.*

Tapi itu termasuk .dan ..juga, jadi bukan itu yang Anda cari. Saya yakin ada cara untuk membuat *dotfiles yang cocok di pesta juga.


Di bash, gunakan .??*untuk mencocokkan semua file titik bukan .dan ... Itu tidak mendapatkan file titik karakter tunggal (seperti .a). Untuk mendapatkannya juga, gunakan yang lebih rumit .[^.]*.
Scott Minster

1

Solusi lain, dengan asumsi jumlah item di folder tidak besar:

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

( ls -Amencetak file normal dan tersembunyi tetapi bukan "." dan ".." seperti ls -ahalnya.)


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

Menentukan .??*akan menyertakan file "titik" dan direktori yang memiliki setidaknya 2 karakter setelah titik. Sisi negatifnya adalah tidak akan menyertakan file / direktori dengan karakter tunggal setelah titik, seperti .a, jika ada.


0

Jika ruang disk bukan masalah, ini juga bisa menjadi hal yang sangat mudah dilakukan:

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

0

Punya situasi yang sama sendiri. Saya pikir yang terbaik adalah membuat tar di tempat lain dan kemudian menggunakan -C untuk memberi tahu tar direktori dasar untuk file yang dikompresi. Contoh:

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

Dengan cara ini tidak perlu mengecualikan tarfile Anda sendiri. Seperti dicatat di komentar lain, -A akan menampilkan file tersembunyi.


0

10 tahun kemudian, Anda memiliki alternatif tar, diilustrasikan dengan Git 2.30 (Q1 2021), yang menggunakan " git archive" ( man ) untuk menghasilkan rilis tarball alih - alih tar.
(Anda tidak perlu Git 2.30 untuk menerapkan alternatif itu)

Lihat commit 4813277 (11 Okt 2020), dan commit 93e7031 (10 Okt 2020) oleh René Scharfe ( rscharfe) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit 63e5273 , 27 Okt 2020)

Makefile: gunakan git init / add / commit / archive untuk dist-doc

Ditandatangani oleh: René Scharfe

Kurangi ketergantungan pada alat eksternal dengan membuat arsip distribusi untuk dokumentasi dan halaman manual HTML menggunakan perintah ( man ), bukan tar. Ini memberi entri arsip data meta yang sama seperti yang ada di arsip dist untuk binari.git

Jadi, alih-alih:

tar cf ../archive.tar .

Anda hanya dapat menggunakan 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

Itu awalnya diusulkan karena, seperti dijelaskan di sini , beberapa platform eksotis mungkin memiliki distribusi tar lama dengan pilihan yang kurang.


-1

Menggunakan findmungkin adalah cara termudah:

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

find . -maxdepth 1akan menemukan semua file / direktori / symlinks / etc di direktori saat ini dan menjalankan perintah yang ditentukan oleh -exec. Di {}dalam perintah berarti daftar file berada di sini dan \+berarti bahwa perintah akan dijalankan sebagai:

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

dari pada

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

-J adalah --xz di manual; dikombinasikan dengan -c hanyalah permulaan dari apa yang komputer sebut "menyenangkan" :)
Ricalsin

Haha, server mini saya di rumah lebih dibatasi oleh ruang disk daripada oleh CPU :) Poin yang bagus; Saya akan mengubahnya untuk menggunakan gzip.
Andrew Gunnerson
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.