Dosyaları bulun ve katranlayın (boşluklarla)


110

Pekala, buradaki çok basit problem. Basit bir yedekleme kodu üzerinde çalışıyorum. Dosyaların içinde boşluklar olması dışında iyi çalışıyor. Dosyaları şu şekilde buluyorum ve bir tar arşivine ekliyorum:

find . -type f | xargs tar -czvf backup.tar.gz 

Sorun, dosyanın adında bir boşluk olması, çünkü tar'ın bir klasör olduğunu düşünmesidir. Temel olarak, find'dan elde edilen sonuçların etrafına alıntı eklemem için bir yol var mı? Veya bunu düzeltmenin farklı bir yolu?


12
find ... | xargs ...Kullanmanın en iyi yolu , her bir: için -print0 / -0 parametresini kullanmaktır find -print0 ... | xargs -0 .... Bu, dosya adlarının boş bir karakterle ayrılmasına neden olur, bu da dosya adlarınızda boşluklar veya satırsonları veya diğer garip şeyler olabileceği anlamına gelir ve yine de çalışır.
porges

8
Çok sayıda dosyanız olduğunda xargs ve tar'ı bu şekilde kullanmakla ilgili bir sorun var, xargs tekrar tekrar tar -c'yi çağıracak ve bu, arşivinizin üzerine yazmaya devam edecek ve sonuç olarak beklediğiniz tüm dosyalara sahip olmayacaksınız. . Bkz bu kadar ayrıntılı bir açıklama ve cevabımı altında.
Steve Kehlet

Yanıtlar:


217

Bunu kullan:

find . -type f -print0 | tar -czvf backup.tar.gz --null -T -

Olacak:

  • boşluklar, satırsonları, baştaki tireler ve diğer komiklikler içeren dosyalarla ilgilen
  • sınırsız sayıda dosyayı işleyin
  • tekrar tekrar kullanmak gibi sizin backup.tar.gz üzerine yazmaz tar -cile xargsdosyaların çok sayıda olduğunda yapacak

Ayrıca bkz:


1
Bulgunuzu önce birkaç kez sed aracılığıyla aktarmak isteseydiniz bunu nasıl yapardınız? örneğin bul. -print0 | sed / yedeklemeler / d | tar ....
Brad Parks

8
Birden fazla koşul varsa parantez eklemeniz gerektiğini unutmayın. Aksi takdirde, -print0yalnızca son ifade için geçerlidir. Egfind . \( -type f -o -name '*.c' \) -print0 | ...
nimrodm

1
Eğlenmek için, işte bunun cygwin kullanan bir Windows sürümü:c:\cygwin\bin\find . -regextype posix-egrep -regex '.*(sln^|vcxproj^|filters)$' -print0 | c:\cygwin\bin\tar -cvf MS_Projects.tar --null -T -
Jon

1
@Steve, tar komutunun sonundaki '-' seçeneğinin ne olduğunu açıklar mısınız? GNU tar'ın man sayfasında bulamıyorum.
shaffooo 01

Elbette, bu bir to parametresidir -Tve dosya adlarını standart girdiden okumak anlamına gelir: --files-from 'için dosya adı olarak tek bir tire verirseniz (yani, --files-from = - veya -T -), sonra dosya adları standart girdiden okunur
Steve Kehlet

14

İstediğinizi elde etmenin başka bir yolu olabilir. Temel olarak,

  1. Aradığınız dosyaların yolunu çıkarmak için find komutunu kullanın . Stdout'u seçtiğiniz bir dosya adına yeniden yönlendirin .
  2. Ardından, dosya konumlarının bir listesini almasına izin veren -T seçeneğiyle tar. (Find ile yeni oluşturduğunuz yer!)

    find . -name "*.whatever" > yourListOfFiles
    tar -cvf yourfile.tar -T yourListOfFiles
    

İçinde satırsonu bulunan dosya adlarının nasıl işleneceğine dair bir cevap burada: superuser.com/a/513319/151261
tommy.carstensen

8

Koşmayı deneyin:

    find . -type f | xargs -d "\n" tar -czvf backup.tar.gz 

7

Neden olmasın:

tar czvf backup.tar.gz *

Elbette bul ve sonra xargs kullanmak zekice, ama sen bunu zor yoldan yapıyorsun.

Güncelleme: Porges, cevabımdan veya diğerinden daha iyi bir cevap olduğunu düşündüğüm bir bul seçeneği ile yorum yaptı: find -print0 ... | xargs -0 ....


Tam kodum yalnızca son bir gün içinde değiştirilen öğeleri yedekleyecek. Günlük bir yedekleme olduğundan, dosya boyutuna kaydetmek için tekrarlanan bilgiler istemiyorum (ayrıca her 15 günde bir tam yedeklemem var).
Caleb Kester

Bunu daha iyi bir SO sorusu yapmak için, "find, xargs ve tar'ı birlikte güvenilir bir şekilde kullanma" hakkındaki soruyu sorardım. Başlığınız ve sorunuz gerçekten bulmanız ve xargs'a ihtiyacınız olduğunu belirtmiyor, ama yine de siz yapıyorsunuz.
Warren P

xargs ... tar c ...dosya listesi çok uzunsa oluşturulan ilk arşivin üzerine xargsyazacak tarve ikinci kez çalıştırılacaktır ! Üzerine yazmayı önlemek için kullanabilirsiniz, xargs -xancak daha sonra arşiv eksik olabilir. Alternatif, önce tar c ...ve sonra muhtemelen tekrar tekrar olabilir tar r .... (güvenilirliğe
katkım

3

Birden fazla dosyanız veya dizininiz varsa ve bunları bağımsız bir *.gzdosyaya sıkıştırmak istiyorsanız, bunu yapabilirsiniz. İsteğe bağlı-type f -atime

find -name "httpd-log*.txt" -type f -mtime +1 -exec tar -vzcf {}.gz {} \;

Bu sıkıştıracak

httpd-log01.txt
httpd-log02.txt

için

httpd-log01.txt.gz
httpd-log02.txt.gz

2

Neden böyle bir şeyi denemiyorsunuz: tar cvf scala.tar `find src -name *.scala`



2

@Steve Kehlet gönderisine bir yorum ekleyecekti ancak 50 rep (RIP) gerekiyor.

Bu gönderiyi çok sayıda googling aracılığıyla bulan herkes için, yalnızca belirli bir zaman aralığı verilen belirli dosyaları bulmanın bir yolunu bulmadım, aynı zamanda katranlama hatalarına neden olabilecek göreli yolları VEYA beyaz boşlukları da dahil etmedim. (ÇOK TEŞEKKÜRLER STEVE.)

find . -name "*.pdf" -type f -mtime 0 -printf "%f\0" | tar -czvf /dir/zip.tar.gz --null -T -
  1. . göreceli dizin

  2. -name "*.pdf" pdf'leri (veya herhangi bir dosya türünü) arayın

  3. -type f aranacak tür bir dosyadır

  4. -mtime 0 son 24 saatte oluşturulan dosyaları ara

  5. -printf "%f\0"Normal -print0VEYA -printf "%f"benim için işe yaramadı. Man sayfalarından:

Bu alıntı, GNU ls ile aynı şekilde yapılır. Bu, -ls ve -fls için kullanılanla aynı alıntı mekanizması değildir. Bul'un çıktısı için hangi formatı kullanacağınıza karar verebiliyorsanız, dosya adları beyaz boşluk ve satırsonu karakterleri içerebileceğinden, normal olarak bir sonlandırıcı olarak '\ 0' kullanmak yeni satır kullanmaktan daha iyidir.

  1. -czvf arşiv oluşturun, arşivi gzip ile filtreleyin, işlenen dosyaları ayrıntılı bir şekilde listeleyin, arşiv adı

Düzenleme 2019-08-14: Eklemek isterim ki, yorumumda esasen aynı komutu sadece tar kullanarak kullanabildim:

tar -czvf /archiveDir/test.tar.gz --newer-mtime=0 --ignore-failed-read *.pdf

--ignore-failed-readBugün için yeni PDF olmaması durumunda gerekli .


1

En iyi çözüm bir dosya listesi oluşturmak ve ardından dosyaları arşivlemektir çünkü diğer kaynakları kullanabilir ve listeyle başka bir şey yapabilirsiniz.

Örneğin bu, arşivlenen dosyaların boyutunu hesaplamak için listenin kullanılmasına izin verir:

#!/bin/sh

backupFileName="backup-big-$(date +"%Y%m%d-%H%M")"
backupRoot="/var/www"
backupOutPath=""

archivePath=$backupOutPath$backupFileName.tar.gz
listOfFilesPath=$backupOutPath$backupFileName.filelist

#
# Make a list of files/directories to archive
#
echo "" > $listOfFilesPath
echo "${backupRoot}/uploads" >> $listOfFilesPath
echo "${backupRoot}/extra/user/data" >> $listOfFilesPath
find "${backupRoot}/drupal_root/sites/" -name "files" -type d >> $listOfFilesPath

#
# Size calculation
#
sizeForProgress=`
cat $listOfFilesPath | while read nextFile;do
    if [ ! -z "$nextFile" ]; then
        du -sb "$nextFile"
    fi
done | awk '{size+=$1} END {print size}'
`

#
# Archive with progress
#
## simple with dump of all files currently archived
#tar -czvf $archivePath -T $listOfFilesPath
## progress bar
sizeForShow=$(($sizeForProgress/1024/1024))
echo -e "\nRunning backup [source files are $sizeForShow MiB]\n"
tar -cPp -T $listOfFilesPath | pv -s $sizeForProgress | gzip > $archivePath

Bunun için bir astar mı?
Robino
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.