tar --exclude hariç değildir. Neden?


71

Ben (yani üreten başarıyla yürüten bir bash komut dosyası bu çok basit çizgi var _data.taro hariç dosyası) değil o aracılığıyla dışlamak anlatılıyor alt dizinleri dışlamak --excludeseçeneği:

/bin/tar -cf /home/_data.tar  --exclude='/data/sub1/*'  --exclude='/data/sub2/*' --exclude='/data/sub3/*'  --exclude='/data/sub4/*'  --exclude='/data/sub5/*'  /data

Bunun yerine, _data.tardışlamak istediğim alt dizinlerdeki dosyalar da dahil olmak üzere / data altındaki her şeyi içeren bir dosya üretir .

Neden bir fikrin var mı? ve bu nasıl düzeltilir?

Güncelleme Gözlemlerimi, aşağıdaki ilk cevapta verilen bağlantıya dayanarak gerçekleştirdim (ilk önce üst düzey dir, son dışlamadan sonra boşluk yok):

/bin/tar -cf /home/_data.tar  /data  --exclude='/data/sub1/*'  --exclude='/data/sub2/*'  --exclude='/data/sub3/*'  --exclude='/data/sub4/*'  --exclude='/data/sub5/*'

Ama bu yardımcı olmadı. Tüm "hariç tutulan" alt dizinler sonuç _data.tardosyasında bulunur.

Bu şaşırtıcı. Bunun şu anki katranda bir böcek (GNU tar 1.23, bir CentOS 6.2, Linux 2.6.32'de) veya katranın beyaz alanlara ve diğer kaçırılması kolay yazım hatalarına "aşırı hassasiyeti" olsun, bunu bir hata olarak görüyorum. Şimdilik.

Bu korkunç : Aşağıda önerilen bilgileri denedim (iz yok /*) ve yapım senaryosunda hala çalışmıyor:

/bin/tar -cf /home/_data.tar  /data  --exclude='/data/sub1'  --exclude='/data/sub2'  --exclude='/data/sub3'  --exclude='/data/sub4'

Ne denedim ve ne @Richard Perrin'in denediği, tırnak işaretleri ve 1 yerine 2 boşluk dışında hiçbir fark göremiyorum. Bunu deneyeceğim (gecelik betiğin yedeklenecek dizin olarak çalışmasını beklemeliyim) yukarı çok büyük) ve geri rapor edin.

/bin/tar -cf /home/_data.tar  /data --exclude=/data/sub1 --exclude=/data/sub2 --exclude=/data/sub3 --exclude=/data/sub4

Tüm bu tar --excludeduyarlılıkların katran değil, çevremdeki bir şey olduğunu düşünmeye başlıyorum , ama sonra bu ne olabilir?

İşe yaradı! --excludeDenenen son varyasyon (s'ler arasında çift boşluk yerine tek tırnaklar ve tek boşluklar yok ) denenmiştir. Garip ama kabul ediyorum.

Inanılmaz! Bu eski bir sürümü çıkıyor tarüst düzey dir ise (1.15.1) sadece dışlayacak son komut satırında. Bu, 1.23 sürümünün gerektirdiğinin tam tersi. Bilginize.

Yanıtlar:


50

Bir dizinin tamamını hariç tutmak istiyorsanız, düzeniniz içindeki dosyalarla değil, bu diziyle eşleşmelidir. Yerine --exclude=/data/sub1kullanın--exclude='/data/sub1/*'

Desenleri kabuk genişlemesinden korumak için alıntı yaparken dikkatli olun.

Son Örnekte sorunlu bu örneğe bakın:

$ for i in 0 1 2; do mkdir -p /tmp/data/sub$i; echo foo > /tmp/data/sub$i/foo; done
$ find /tmp/data
/tmp/data
/tmp/data/sub2
/tmp/data/sub2/foo
/tmp/data/sub0
/tmp/data/sub0/foo
/tmp/data/sub1
/tmp/data/sub1/foo
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude='/tmp/data/sub[1-2]'
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub0/
/tmp/data/sub0/foo
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub0/
/tmp/data/sub0/foo
$ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
tar -zvcf /tmp/_data.tar /tmp/data --exclude=/tmp/data/sub[1-2]
$ tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2]
tar: Removing leading `/' from member names
/tmp/data/
/tmp/data/sub2/
/tmp/data/sub2/foo
/tmp/data/sub0/
/tmp/data/sub0/foo
/tmp/data/sub2/
tar: Removing leading `/' from hard link targets
/tmp/data/sub2/foo
$ echo tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub[1-2]
tar -zvcf /tmp/_data.tar /tmp/data --exclude /tmp/data/sub1 /tmp/data/sub2

Çok odaklı ve net cevap için teşekkürler. 1. puanınızla ilgili olarak, bu LQ başlığındaki ipuçlarını takip etmeye çalışıyordum . Neyi özlediğimden emin değilim, ama şimdi 2. noktanızı okuduğumdan, göreceli olarak mutlak bir yol sorunu olabilir. Bunu deneyeceğim ve tekrar rapor edeceğim. Şimdilik +1.
ateiob

Fark başka şeydir --exclude b(boşluk yerine eşit işareti) vs --exclude=b. Bu herhangi bir fark yaratıyor mu? (IMHO olmamalı)
ateiob

1
Eşit olmayan işaretler, çizilmemiş desenlerin kabuk genişlemesini önlemek için gerekli olabilir. Bunun yerine bir boşluk varsa, kabuksuz bir desen kabuk tarafından tek - dışlamalı bir argümana genişletilebilir ve kalan genişlemeler tar dosyasına eklenecek dosyalar olarak verilir. Her şeyden önce örneklerinizde '=' var - eğer komut dosyası yoksa ve tek tırnaklar eksikse, o zaman sorunun kaynağı olabilir.
R Perrin

TAMAM. Örneğimi kutumda test ettim ve aynı hatta birden fazla olsa bile çalışır --exclude=. Bu yüzden fark /*, her bir alt dizine eklediğim aptal olmalı . Bu gece prodüksiyon senaryosunda test edip geri rapor edeceğim. Başka bir +1.
ateiob

Benim için, @ carlo'nun cevabı belirli bir sorundu - aptal katran alınamaz - komut satırındaki son seçenek olarak dışlanır - açıkçası çok fazla baş ağrısına neden olur. Hepinize teşekkürler.
moodboom

32

Seçenek sürümünüzde tar, --excludeseçeneklerin tarkomutun başına yerleştirilmesi gerekebilir .

Bakınız: https://stackoverflow.com/q/984204

tar --exclude='./folder' --exclude='./upload/folder2' \
    -zcvf /backup/filename.tgz .

Bakınız: http://mandrivausers.org/index.php?/topic/8585-multiple-exclude-in-tar/

tar --exclude=<first> --exclude=<second> -cjf backupfile.bz2 /home/*

Alternatif:

EXCLD='first second third'
tar -X <(for i in ${EXCLD}; do echo $i; done) -cjf backupfile.bz2 /home/*

Yine başka bir tarkomut ipucu buradan :

tar cvfz myproject.tgz --exclude='path/dir_to_exclude1' \
                       --exclude='path/dir_to_exclude2' myproject

Yukarıdaki güncellememe bakın. Denenen son varyasyon (tırnak işareti yok, tek boşluk) çalışıyor. Neden olduğuna dair hiçbir fikrim yok. İyi düşünülmüş cevap + bağlantılar için +1.
ateiob,

FYI, debian altında, Filtreyi kesin olarak söylemezsem, --exclude=mydir/*o zamanki gibi (işe yaramazsa tar --exclude=maindir/mydir/* -cjf archive.tar2.bz2 maindir/*) çalışmaz .
Olivier Pons

1
"Debian" yerine @OlivierPons, belki de onunla tar ( tar --version); Debian'ın yıllar boyunca tar'nın birçok farklı versiyonuyla geleceği tahmin ediliyor.
msouth,

1
Benim sürümü (1.29) sadece çalışır --excludeönce -czf.
falsePockets

8

Birden fazla dosyayı hariç tutmak için deneyin

--exclude=/data/{sub1,sub2,sub3,sub4}

Bu, bazı kod ve baş ağrısından kurtarır. Bu her türlü program / seçenek için küresel bir çözümdür. Ayrıca ana dizini seçiminize dahil etmek istiyorsanız (bu durumda verilere), izleyen bir virgül eklemeniz gerekir. Örneğin:

umount /data/{sub1,sub2,}

3
Kıvırcıkları severim. Yıllarca süren unix deneyiminde bile birçok insanın onlar hakkında bilmediğini biliyorum. mv /very/very/very/very/long/path/to/a/file{,.bak}
msouth,

5

Bu bağlantı yardımcı olabilir. http://answers.google.com/answers/threadview/id/739467.html

Çalışmayan çizgi ile bağlantıdaki bazı ipuçları arasındaki iki acil fark:

  1. Tüm hariç tutmalar , üst düzey dizinden sonra gelir .
  2. Sonundan sonra herhangi bir boşluk olamaz --exclude.

Teşekkürler. Cevabım -MAKdikkatimi çekti ve şu ana kadar çalışmayan çizgim ile aşağıdakiler arasındaki şu farkları belirleyebildim: 1. Tüm hariç tutmalar , üst düzey dizinden sonra gelir . 2. Sonundan sonra herhangi bir boşluk olamaz --exclude. Bu öngörüleri test edip rapor edeceğim. Şimdilik +1.
ateiob

@ateiob Bunu çözerseniz, buraya bir cevap gönderebilir veya bunu düzenleyebilir misiniz? Genel olarak, başka hiçbir yerde bağlantı olan cevapları
almamayı

@Michael Mrozek Kesinlikle. Bu tam olarak yorumuma yazdığım şeydi. :)
ateiob

3

Geçici bir çözüm , belirtilen dizinleri bir arada kullanmak find ... -pruneve tardışlamak olabilir.

Mac OS X'te --excludeGNU seçeneği tarolması gerektiği gibi çalışıyor gibi görünüyor.

Aşağıdaki test durumunda, dizinler /private/var/log/aslve dizinin /private/var/log/DiagnosticMessagessıkıştırılmış bir arşivinden çıkarılmalıdır /private/var/log.

# all successfully tested in Bash shell on Mac OS X (using gnutar and gfind)

# sudo port install findutils  # for gfind from MacPorts

sudo gnutar -czf ~/Desktop/varlog.tar.gz /private/var/log --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages"

sudo gnutar -czf ~/Desktop/varlog.tar.gz  --exclude "/private/var/log/asl" --exclude "/private/var/log/DiagnosticMessages" /private/var/log

set -f # disable file name globbing
sudo gnutar -czf ~/Desktop/varlog.tar.gz  --exclude "/private/var/log/asl" --exclude "/private/var/log/Diagnostic*" /private/var/log

# combining GNU find and tar (on Mac OS X)

sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "DiagnosticMessages" \) -prune -o -print0 | 
   sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from -

# exclude even more dirs
sudo gfind /private/var/log -xdev -type d \( -name "asl" -o -name "[Dacfks]*" \) -prune -o -print0 | 
    sudo gnutar --null --no-recursion -czf ~/Desktop/varlog.tar.gz --files-from -


# testing the compressed archive

gnutar -C ~/Desktop -xzf ~/Desktop/varlog.tar.gz

sudo gfind /private/var/log ~/Desktop/private \( -iname DiagnosticMessages -or -iname asl \)

sudo rm -rf ~/Desktop/varlog.tar.gz ~/Desktop/private

Öneri için +1 teşekkür ederiz. Bu noktada, iyi bir şekilde belgelenmiş (ve olgun) bir özelliğin neden her gece cron tarafından çalıştırılan senaryomda çalışmadığını anlamaya çalışıyorum.
12'de ateiob

3

Belki de komutu başka bir seçenekle deneyebilirsiniz:

--wildcards

Ve istenildiği gibi çalışıp çalışmadığını kontrol edin.


Yukarıdaki güncellememe bakın. Denenen son varyasyon (tırnak işareti yok, tek boşluk) çalışıyor. Neden olduğuna dair hiçbir fikrim yok. Fikir için +1.
ateiob

3

Bir mac kullanıyorum ve üst düzey klasör son argüman olmadığı sürece hariç tutulanların çalışmadığını buldu.

çalışma komutu örneği:

tar czvf tar.tgz --exclude='Music' dir

Bilginize:

$: tar --version
bsdtar 2.8.3 - libarchive 2.8.3

Aynısı, Ubuntu 14.04 üzerinden tar 1.27.1 ile birlikte.
Greg Bell

3

Benim durumumda, farklı bir nedenden dolayı dışlanmadı.

Tam yol, göreceli yol.

Hem dışlama hem de dizin aynı yol biçimini kullanmalıdır (yani hem tam yol hem de her iki bağıl yol)

Örnek:

tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' ctms-db-sync

Bu işe yaramayacak çünkü hariç tutma, hedefin göreli yolu kullandığı tam yolu kullanır

tar -cvf ctms-db-sync.tar --exclude='/home/mine/tmp/ctms-db-sync/sql' /home/mine/tmp/ctms-db-sync

Bu işe yarıyor çünkü her ikisi de tam yolu kullanıyor

tar -cvf ctms-db-sync.tar --exclude='ctms-db-sync/sql' ctms-db-sync

Bu işe yarar çünkü her ikisi de göreceli yolu kullanır.



1

R Perrin'in mükemmel cevabına ek notlar :

Mutlak ama göreceli yolları arşivlemek istemediğinizi varsayalım, örneğin '/ tmp / data' yerine 'data'. Mutlak yolları hariç tutmak için tar argümanlarınız, kullandığınız tar uygulamasına (gnu tar vs. bsd tar) göre değişir:

$ for i in 0 1 2; do
    for j in 0 1 2; do 
      mkdir -p /tmp/data/sub$i/sub$j
      echo foo > /tmp/data/sub$i/sub$j/foo
    done
  done

$ find /tmp/data/
/tmp/data/
/tmp/data/sub2
/tmp/data/sub2/sub2
/tmp/data/sub2/sub2/foo
/tmp/data/sub2/sub1
/tmp/data/sub2/sub1/foo
/tmp/data/sub2/sub0
/tmp/data/sub2/sub0/foo
/tmp/data/sub1
/tmp/data/sub1/sub2
/tmp/data/sub1/sub2/foo
/tmp/data/sub1/sub1
/tmp/data/sub1/sub1/foo
/tmp/data/sub1/sub0
/tmp/data/sub1/sub0/foo
/tmp/data/sub0
/tmp/data/sub0/sub2
/tmp/data/sub0/sub2/foo
/tmp/data/sub0/sub1
/tmp/data/sub0/sub1/foo
/tmp/data/sub0/sub0
/tmp/data/sub0/sub0/foo

$ cd /tmp/data; tar -zvcf /tmp/_data.tar --exclude './sub[1-2]'
./
./sub0/
./sub0/sub2/
./sub0/sub2/foo
./sub0/sub1/
./sub0/sub1/foo
./sub0/sub0/
./sub0/sub0/foo

# ATTENTION: bsdtar's behaviour differs from traditional tar (without a leading '^')!
$ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude './sub[1-2]' .
a .
a ./sub0
a ./sub0/sub0
a ./sub0/sub0/foo

# FIX: Use a regex by adding a leading '^' will cause bsdtar to match only parent files and folders.
$ cd /tmp/data; bsdtar -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' .
# ALTERNATIVE: bsdtar -C /tmp/data -zvcf /tmp/_data.tar --exclude '^./sub[1-2]' .
a .
a ./sub0
a ./sub0/sub2
a ./sub0/sub1
a ./sub0/sub0
a ./sub0/sub0/foo
a ./sub0/sub1/foo
a ./sub0/sub2/foo

1

Az önce tar (GNU tar) 1.29'da tespit edildi

Bu çağrı --exclude-from ile belirtilen arşiv dosyalarının dışında bırakılmaz:

/bin/tar --files-from ${datafile} --exclude-from ${excludefile} -jcf ${backupfile}

Bu çağrı koordineli olarak çalışır:

/bin/tar --exclude-from ${excludefile} --files-from ${datafile} -jcf ${backupfile}

Parametrelerin sırası önemlidir!


0

Listelenen cevapların bir kısmı da dahil olmak üzere her türlü kombinasyonu denedim ve listelenen dosyaları dışlamak için bir türlü bulamadım.

Böylece, beş dakikalık bir iş olması gereken şeyin cevabını kovalamaktan bıktım, tam tersini yaptım: eklemek istediğim klasörlerin bir arşivini yarattım .

Bunu bir arşiv oluşturup sonra ekleyerek yaptım :

tar -cvpf /path/to/mybackup.tar ./bin
tar rvf /path/to/mybackup.tar ./boot
tar rvf /path/to/mybackup.tar ./etc
tar rvf /path/to/mybackup.tar ./home
tar rvf /path/to/mybackup.tar ./lib
tar rvf /path/to/mybackup.tar ./sbin
tar rvf /path/to/mybackup.tar ./usr
tar rvf /path/to/mybackup.tar ./var

Birkaç not:

  • Dosya sisteminin kökünden çalıştırarak göreceli mutlak yollar (aynı zamanda sorun çıkarmakta) yerine kullandım.
  • Bir düz tar(ve sıkıştırılmış tar .tgz/ değil .tar.gz) arşivi oluşturmalısınız - daha sonragzip mybackup.tar
  • Arşivi dahil ettiğiniz herhangi bir klasöre koymadığınızdan emin olun, aksi halde biraz özyinelemeye sahip olacaksınız (yedeğin içine de dahil olan kısmi bir yedekleme).
  • İlk komuttaki (yarat) diğerlerinden (ekle) farkı görün.
  • Kullanarak paranoyak kullanıyorsanız, üzerine yazılan yedeklemeden ziyade dosyaların eklendiğini kontrol edebilirsiniz (örneğin, ikinci komuttan sonra) tar tvf mybackup.tar.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.