web-dev-qa-db-fra.com

Comment puis-je remplacer les deux-points lorsque je rsync sur une clé USB?

Je souhaite sauvegarder mon répertoire de messagerie sur une clé USB. Cependant, mon protocole IMAP a une convention de nommage étrange selon laquelle quelque chose inclut un caractère deux-points (:). Comme la clé USB est dans un format de fenêtre, rsync ne parvient pas à créer ces fichiers. Est-il possible de remplacer le caractère deux-points par un trait de soulignement lors de l'exécution de rsync? (Ou faire la même synchronisation avec un autre outil?)

Juste un point que j'ai clarifié dans les commentaires:

  • Ceci est un pire scénario sauvegarde, je voudrais pouvoir le lire sur une machine Windows sans rien installer.
  • J'ai beaucoup de données qui restent constantes. Je gagne donc beaucoup de temps si je dispose d’un outil qui ne fait que copier les fichiers les plus récents.
  • Je ne cherche pas une réécriture de rsync. Je recherche un outil existant qui peut être utilisé directement.

Merci

12
Guillaume Coté

Utilisez rdiff-backup au lieu de plain rsync. Il détectera et remplacera automatiquement les caractères qui ne sont pas pris en charge sur le disque de destination et les remettra comme ils étaient lors de la restauration sur un système de fichiers Unix. Il produit un répertoire décompressé qui ressemble à l’origine, plus un répertoire de métadonnées supplémentaire.

8
poolie

L'approche la plus simple consiste à utiliser la couche de système de fichiers pour transformer les noms de fichier. Depuis Ubuntu 12.04, il existe un système de fichiers Fuse qui transforme les noms de fichiers en noms pris en charge par VFAT de Windows: Fuse-posixovlInstall Fuse-posixovl .

Sudo mount.posixovl /media/sdb1
chown guillaume /media/sdb1
rsync -au ~/mail /media/sbd1/

Ou pour éviter de nécessiter un accès root:

mkdir ~/mnt
/sbin/mount.posixovl -S /media/sdb1 ~/mnt
rsync -au ~/mail ~/mnt/

Les caractères dans les noms de fichiers que VFAT n'accepte pas sont codés sous la forme %(XX)XX sont des chiffres hexadécimaux. A partir de POSIXovl 1.2.20120215, sachez qu'un nom de fichier tel que %(3A) est codé comme tel et qu'il sera décodé en tant que :. Il existe donc un risque de collision si vous avez des noms de fichier contenant des sous-chaînes de la forme %(XX).

Attention, POSIXovl ne gère pas les noms de fichiers trop longs. Si le nom codé ne contient pas 255 caractères, le fichier ne peut pas être stocké.

POSIXovl stocke les autorisations Unix et la propriété dans des fichiers nommés .pxovl.FILENAME.


Le script bash ≥4 suivant copie ~/mail/foo:bar vers /media/usb99/mail/foo_bar et de la même manière pour tous les fichiers sous ~/mail. Les fichiers qui existent déjà dans l'arborescence de destination et qui ne sont pas plus anciens que la source sont ignorés.

#!/bin/bash
set -e
shopt -s dotglob globstar
for source in "$HOME"/mail/**/*; do
  target=/media/usb99/${source#"$HOME"/}
  target=${target//:/_}
  if [[ -d $source ]]; then
    mkdir -p -- "$target"
  Elif [[ $target -ot $source ]]; then
    cp -p -- "$source" "$target"
  fi
done

Ce script fonctionne sous zsh avec des modifications mineures: remplacez shopt -s dotglob globstar par setopt dot_glob et [[ $target -ot $source ]] par [[ ! -e $target || $target -ot $source ]].


Voici un zsh two-liner (trois si vous comptez les autoloads). C'est plus court, mais assez avancé et pas très lisible.

autoload zargs zmv
zargs -- ~/mail/**/*(/e\''REPLY=/media/usb99/${${REPLY#$HOME/}//:/_}'\') -- mkdir -p --
zmv -C -Q -o -pu '~/mail/(**/)(*)(.)' '/media/usb99/mail/${1//:/_}${2//:/_}'
  • La ligne zargs est équivalente à mkdir -p ~/mail/**/*(…), sauf qu'elle ne bombardera pas si la longueur cumulée des noms de répertoire est trop longue. Cette ligne crée les répertoires cibles nécessaires.
  • ~/mail/**/*(/) se développe dans tous les répertoires sous ~/mail (répertoires uniquement en raison du (/) à la fin).
  • (/e\''…'\') sélectionne uniquement les répertoires et exécute ensuite le code entre '…' pour transformer chaque nom de fichier, qui est stocké dans la variable REPLY.
  • ${${REPLY#$HOME/}//:/_} supprime le préfixe correspondant au répertoire source et remplace : en _.
  • zmv -C copie chaque fichier correspondant à son premier opérande (un motif zsh) vers le nom de fichier obtenu en développant son second opérande.
  • -o -pu dit de passer -pu à l'utilitaire cp, de manière à conserver les autorisations et à ne copier que les fichiers mis à jour. (Nous pourrions dire à zsh d'effectuer la vérification de la mise à jour; ce serait un peu plus rapide mais encore plus cryptique.)
  • (.) sélectionne uniquement les fichiers normaux. -Q indique que cela doit être analysé comme un qualificatif global et non comme un . entouré de parenthèses indiquant une sous-expression.
  • $1 et $2 dans le texte de remplacement correspondent aux expressions entre parenthèses (**/) et *. (** perd sa signification particulière en tant que zéro ou plusieurs niveaux de sous-répertoires s'il est entre parenthèses, à moins que les parenthèses ne contiennent exactement **/.)

J'ai d'abord pensé utiliser pax , qui est un outil d'archivage (ici destiné à être utilisé en mode de passage) qui possède une fonctionnalité de changement de nom de fichier (son option -s). Cependant, les options -s et -u ne fonctionnent pas ensemble (le définition POSIX de pax indique littéralement que -u doit vérifier un fichier du même nom dans le répertoire. l’arborescence de destination plutôt que le nom de fichier transformé par -s, l’implémentation de pax dans Ubuntu suit la spécification au lieu d’utile). Il est encore possible de l'utiliser pour créer des liens physiques renommés, puis de copier les liens physiques (avec rsync -au ou pax -rw -pp -u) sur un autre support, mais cela ne vaut pas la peine.

cd ~/mail
mkdir -p /media/usb99/mail
pax -rw -l -pp -s '!:!_!g' . ../mail.colonless
rsync -au ../mail.colonless/ /media/usb99/mail/
6
Gilles