Tar direktori, tetapi jangan menyimpan path absolut penuh dalam arsip

277

Saya memiliki perintah berikut di bagian skrip shell cadangan:

tar -cjf site1.bz2 /var/www/site1/

Ketika saya daftar isi arsip, saya mendapatkan:

tar -tf site1.bz2
var/www/site1/style.css
var/www/site1/index.html
var/www/site1/page2.html
var/www/site1/page3.html
var/www/site1/images/img1.png
var/www/site1/images/img2.png
var/www/site1/subdir/index.html

Tetapi saya ingin menghapus bagian /var/www/site1dari direktori dan nama file dalam arsip, untuk menyederhanakan ekstraksi dan menghindari struktur direktori konstan yang tidak berguna. Tidak pernah tahu, kalau-kalau saya akan mengekstrak situs web yang dicadangkan di tempat data web tidak disimpan /var/www.

Untuk contoh di atas, saya ingin memiliki:

tar -tf site1.bz2
style.css
index.html
page2.html
page3.html
images/img1.png
images/img2.png
subdir/index.html

Jadi, ketika saya mengekstrak, file diekstraksi dalam direktori saat ini dan saya tidak perlu memindahkan file yang diekstrak setelahnya, dan agar struktur sub-direktori dipertahankan.

Sudah ada banyak pertanyaan tentang tar dan cadangan di stackoverflowdan di tempat-tempat lain di web, tetapi kebanyakan dari mereka meminta untuk menjatuhkan seluruh struktur sub-direktori (perataan), atau hanya menambah atau menghapus inisial / dalam nama (saya tidak Saya tidak tahu apa yang berubah tepat saat mengekstraksi), tetapi tidak lebih.

Setelah membaca beberapa solusi yang ditemukan di sana-sini serta manual, saya mencoba:

tar -cjf site1.bz2 -C . /var/www/site1/
tar -cjf site1.bz2 -C / /var/www/site1/
tar -cjf site1.bz2 -C /var/www/site1/ /var/www/site1/
tar -cjf site1.bz2 --strip-components=3 /var/www/site1/

Tapi tidak satu pun dari mereka yang bekerja seperti yang saya inginkan. Beberapa tidak melakukan apa-apa, beberapa lainnya tidak lagi mengarsipkan sub-direktori.

Itu ada di dalam skrip shell cadangan yang diluncurkan oleh Cron, jadi saya tidak tahu, pengguna mana yang menjalankannya, apa path dan direktori saat ini, jadi selalu menulis path absolut diperlukan untuk semuanya, dan lebih suka tidak mengubah direktori saat ini untuk menghindari melanggar sesuatu lebih lanjut dalam skrip (karena tidak hanya membuat cadangan situs web, tetapi juga database, kemudian mengirim semua itu ke FTP dll.)

Bagaimana cara mencapai ini?

Apakah saya salah mengerti bagaimana opsi -C bekerja?

QuentinC
sumber
terkait: unix.stackexchange.com/questions/22842/tar-with-relative-paths | serverfault.com/questions/339762/…
Ciro Santilli 郝海东 冠状 病 六四 事件 事件
Ya, -Cberarti "ganti direktori", sementara mengganti jalur (atau awalan) hanya bisa dilakukan oleh --transform. rif. superuser.com/questions/595510/prepend-prefix-in-tar/595512 Anda dapat simpel -C (ubah direktori) dan --transformasi: `` `tar cjf site1.bz2 --transform" s / ^ \. \ // $ targetbase / "-C / var / www / site1. `` `
Daniele Cruciani
Ini adalah pertanyaan yang sangat bagus dan sayangnya tidak ada jawaban untuk tanggal ini yang memuaskan. Kami belum mendengar dari beberapa orang bijak bagaimana kami bisa mengekstrak hanya file style.css tunggal (contoh di atas) ke direktori saat ini tanpa referensi ke lokasi asli atau pohon direktori? Saya tidak ingin mengacaukan direktori saya saat ini dengan struktur pohon baru yang tidak diinginkan. Kedengarannya seperti kekurangan tarball serius yang telah diabaikan selama bertahun-tahun.
elmclose

Jawaban:

383
tar -cjf site1.tar.bz2 -C /var/www/site1 .

Pada contoh di atas, tar akan berubah ke direktori /var/www/site1sebelum melakukan hal itu karena opsi -C /var/www/site1diberikan.

Dari man tar:

OTHER OPTIONS

  -C, --directory DIR
       change to directory DIR
Lars Brinkhoff
sumber
152
Jangan lewatkan titik di bagian akhir, itu penting ;-)
Freedom_Ben
9
bagaimana kalau Anda juga ingin memilih file yang akan dibackup berdasarkan wildcard? -C / var / www / site1 * .dat tidak berfungsi :(
Andy Lorenz
16
Titik memberitahu tararsip semua di direktori saat ini. Dan -Cmengatur direktori saat ini.
Lars Brinkhoff
21
Ini sangat bagus. Saya merasa berguna untuk mempertahankan nama direktori (tidak hanya path lengkap), jadi saya melakukan hal berikut: tar -czvf site1.tar.gz -C /var/www/ site1(Perhatikan spasi, saya masih menggunakan -C, untuk cd ke dir induk, dan menentukan dir ke tar bukannya dot)
jorfus
9
Saya mendapatkan titik terdepan di jalur tar misalnya ./foldersbagaimana ini bisa dihapus?
Mika571
39

Opsi ini -Cberfungsi; hanya untuk klarifikasi saya akan memposting 2 contoh:

  1. pembuatan tarball tanpa path lengkap: path penuh /home/testuser/workspace/project/application.wardan apa yang kita inginkan hanyalah project/application.war:

    tar -cvf output_filename.tar  -C /home/testuser/workspace project

    Catatan: ada ruang antara workspacedan project; tar akan mengganti path lengkap dengan adil project.

  2. ekstraksi tarball dengan mengubah jalur target (default ke ., yaitu direktori saat ini)

    tar -xvf output_filename.tar -C /home/deploy/

    tarakan mengekstrak tarball berdasarkan jalur yang diberikan dan melestarikan jalur penciptaan; dalam contoh kita file application.warakan diekstraksi ke /home/deploy/project/application.war.

    /home/deploy: diberikan pada ekstrak
    project: diberikan pada pembuatan tarball

Catatan: jika Anda ingin menempatkan tarball yang dibuat di direktori target, Anda cukup menambahkan path target sebelum nama tarball. misalnya:

tar -cvf /path/to/place/output_filename.tar  -C /home/testuser/workspace project
Grizli
sumber
1
bagaimana cara menambahkan wildcard untuk pemilihan file pada contoh terakhir?
Siva
Masalah dengan wildcard adalah bahwa shell mengekspansi mereka ke nama file yang cocok dan tar itu tidak memperluas mereka jika mereka dikutip ...
Gert van den Berg
Saya mencoba ini di Ubuntu 18.04 dan tidak berhasil. Saya tidak yakin apa yang saya lewatkan. Stdout saya menampilkannya dengan benar ketika saya mengemasnya, tetapi ketika saya membukanya, ia masih memiliki path lengkap
sdc
14

Tampaknya -Copsi upto tar v2.8.3 tidak bekerja secara konsisten pada semua platform (OS). -Copsi dikatakan menambahkan direktori ke arsip tetapi pada Mac dan Ubuntu ia menambahkan awalan path absolut di dalam file tar.gz yang dihasilkan.

tar target_path/file.tar.gz -C source_path/source_dir

Oleh karena itu solusi yang konsisten dan tangguh adalah cdmasuk ke source_path (direktori induk dari source_dir) dan jalankan

tar target_path/file.tar.gz source_dir

atau

tar -cf target_path/file.tar.gz source_dir

dalam naskah Anda. Ini akan menghapus awalan path absolut dalam struktur direktori file tar.gz yang Anda hasilkan.

Chinthaka Senanayaka
sumber
1
Penggunaan opsi -C DID menghapus awalan path absolut di dalam file tar.gz yang dihasilkan pada fedora 29. Apakah jawaban Anda spesifik untuk beberapa sistem?
EL_DON
@EL_DON: Saya tidak menguji opsi -C pada Fedora, tetapi idealnya perangkat lunak aplikasi tar harus bekerja secara konsisten pada setiap platform kecuali itu adalah bug dalam aplikasi tar. Opsi -C, saya uji pada Mac 10.8 dan Mac 10.13 dan Ubuntu (versi saya tidak ingat). Tetapi pada tar v2.8.3, perintah telah diubah menjadi tar -cf target_path / file.tar.gz source_dir dan masih jika Anda menambahkan opsi -C itu tidak akan menghapus awalan path absolut di dalam file tar.gz yang dihasilkan.
Chinthaka Senanayaka
Saya menguji lagi pada sistem centOS. Setelah membuat semua path dalam contoh dan menjalankan perintah (dengan -cvfditambahkan setelah tar), saya menemukan file tar.gz yang dihasilkan tidak memiliki path absolut di dalamnya, yang konsisten dengan beberapa jawaban lainnya. Jika menurut Anda tar rusak atau ketinggalan zaman pada kedua sistem yang saya gunakan untuk pengujian, harap tautkan ke beberapa dokumentasi yang akan mendukung jawaban Anda. Saya pikir -Copsi ini mengubah direktori sebelum mengeksekusi (seperti pada jawaban lain). Ketika saya menghilangkannya, tar mencoba menambahkan sampah dari ./, termasuk jalur dari mulai dari ./.
EL_DON
Saya menggunakan doc ini: linux.die.net/man/1/tar Ya, doc mengatakan -C akan melakukan perubahan jalur, tetapi pada Mac saya 10,13 tidak berfungsi. ini bisa menjadi perilaku aplikasi tar yang tidak konsisten. Itu artinya ini adalah bug. Jika Anda menulis skrip shell untuk dijalankan pada semua platform unix maka lebih baik aman dengan menjalankan kode yang akan bekerja pada semua OS.
Chinthaka Senanayaka
Jawaban Anda tidak mengatakan bahwa mungkin ada bug dan solusi yang lebih kuat untuk kompatibilitas lintas platform adalah yang cdpertama. Jawaban Anda mengatakan alat ini bekerja dengan cara yang berlawanan dengan bagaimana dokumen mengatakan itu bekerja dan bagaimana cara kerjanya pada sistem saya, jadi itu adalah jawaban yang salah. Anda dapat dengan mudah memperbaikinya.
EL_DON
7

Perintah berikut akan membuat direktori root "." dan letakkan semua file dari direktori yang ditentukan ke dalamnya.

tar -cjf site1.tar.bz2 -C /var/www/site1 .

Jika Anda ingin meletakkan semua file di root dari file tar, @chinthaka benar. Cukup masuk ke direktori dan lakukan:

tar -cjf target_path/file.tar.gz *

Ini akan menempatkan semua file di cwd ke file tar sebagai file root.

WLatif
sumber
1
Menggunakan * tidak menyimpan file "tersembunyi". Atau folder. (fyi, menggunakan -C bersama dengan * gagal, shell memperluas direktori saat ini, bukan direktori -C)
Xen2050
1

Menggunakan "titik" mengarah ke pembuatan folder bernama "titik" (di Ubuntu 16).

tar -tf site1.bz2 -C /var/www/site1/ .

Saya membahas hal ini lebih terinci dan menyiapkan contoh. Rekaman multi-line, ditambah pengecualian.

tar -tf site1.bz2\
    -C /var/www/site1/ style.css\
    -C /var/www/site1/ index.html\
    -C /var/www/site1/ page2.html\
    -C /var/www/site1/ page3.html\
    --exclude=images/*.zip\
    -C /var/www/site1/ images/
    -C /var/www/site1/ subdir/
/
Sergey Asachev
sumber
Mengapa Anda menyebutnya "titik"? Hanya saja ., yang merupakan direktori saat ini. Dalam konteks tar.gzstruktur, itu hanya level dasar / root / atas, kan?
EL_DON
Lihat foto untuk detail gambar . Cara saya lebih tepat digunakan, Ini menurut saya.
Sergey Asachev
0

Jika Anda ingin mengarsipkan subdirektori dan memangkas jalur subdirektori, perintah ini akan berguna:

tar -cjf site1.bz2 -C /var/www/ site1
Hirurg103
sumber