web-dev-qa-db-fra.com

Trouver des fichiers et les tar (avec des espaces)

Bon, si simple problème ici. Je travaille sur un simple code de sauvegarde. Cela fonctionne très bien sauf si les fichiers ont des espaces. Voici comment je trouve des fichiers et les ajoute à une archive tar:

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

Le problème vient du fait que le nom du fichier est un espace car tar pense que c'est un dossier. Existe-t-il un moyen de rajouter des guillemets autour des résultats de find? Ou une autre façon de résoudre ce problème?

106
Caleb Kester

Utilisez ceci:

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

Ce sera:

  • traiter les fichiers avec des espaces, des retours à la ligne, des tirets, et autres fonctions amusantes
  • gérer un nombre illimité de fichiers
  • ne remplacera pas votre backup.tar.gz de manière répétée, comme si vous utilisiez tar -c avec xargs fera l'affaire lorsque vous avez un grand nombre de fichiers

Regarde aussi:

205
Steve Kehlet

Il pourrait y avoir un autre moyen de réaliser ce que vous voulez. Fondamentalement,

  1. Utilisez la commande find pour indiquer le chemin d'accès aux fichiers recherchés. Rediriger stdout vers un nom de fichier de votre choix.
  2. Puis tar avec l'option -T qui lui permet de prendre une liste d'emplacements de fichiers (celui que vous venez de créer avec find!)

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

Essayez de courir:

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

Pourquoi pas:

tar czvf backup.tar.gz *

Bien sûr, il est intelligent d’utiliser find, puis xargs, mais vous le faites à la dure.

Mise à jour: Porges a commenté avec une option de recherche que je pense être une meilleure réponse que ma réponse, ou l'autre: find -print0 ... | xargs -0 ....

7
Warren P

Si vous avez plusieurs fichiers ou répertoires et que vous souhaitez les compresser dans un fichier indépendant *.gz, Vous pouvez le faire. Facultatif -type f -atime

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

Cela va compresser

httpd-log01.txt
httpd-log02.txt

à

httpd-log01.txt.gz
httpd-log02.txt.gz
3
Kalibur x

Pourquoi ne pas essayer quelque chose comme ceci: tar cvf scala.tar `find src -name *.scala`

2
Frank Eggink

Une autre solution comme on le voit ici :

find var/log/ -iname "anaconda.*" -exec tar -cvzf file.tar.gz {} +
2
tommy.carstensen

Souhaite ajouter un commentaire à @ Steve Kehlet post mais nécessite 50 reps (RIP).

Pour tous ceux qui ont trouvé ce message grâce à de nombreuses recherches sur Google, j'ai trouvé un moyen non seulement de trouver des fichiers spécifiques dans un intervalle de temps, mais également de NE PAS inclure les chemins relatifs OR espaces blancs qui provoqueraient des erreurs de tarage. (MERCI SO BEAUCOUP DE STEVE.)

find . -name "*.pdf" -type f -mtime 0 -printf "%f\0" | tar -czvf /dir/Zip.tar.gz --null -T -
  1. . répertoire relatif

  2. -name "*.pdf" chercher des fichiers PDF (ou n’importe quel type de fichier)

  3. -type f le type à rechercher est un fichier

  4. -mtime 0 rechercher des fichiers créés au cours des dernières 24 heures

  5. -printf "%f\0" Ordinaire -print0 OR -printf "%f" N'a pas travaillé pour moi. À partir des pages de manuel:

Cette citation est effectuée de la même manière que pour GNU ls. Ce mécanisme de citation n'est pas le même que celui utilisé pour -ls et -fls. Si vous êtes en mesure de décider quel format utiliser pour la sortie de find, il est généralement préférable d'utiliser "\ 0" comme terminateur que d'utiliser une nouvelle ligne, car les noms de fichiers peuvent contenir des espaces et des caractères de nouvelle ligne.

  1. -czvf créer une archive, filtrer l’archive avec gzip, lister verbalement les fichiers traités, nom de l’archive

Edit 2019-08-14: J'aimerais ajouter que j'ai également pu utiliser essentiellement la même commande dans mon commentaire, en utilisant uniquement tar lui-même:

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

Nécessaire --ignore-failed-read au cas où il n'y aurait pas de nouveau PDF pour aujourd'hui.

1
user3472383

La meilleure solution semble être de créer une liste de fichiers, puis d'archiver des fichiers, car vous pouvez utiliser d'autres sources et faire autre chose avec la liste.

Par exemple, cela permet d’utiliser la liste pour calculer la taille des fichiers en cours d’archivage:

#!/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
1
Nux