L'approccio più semplice è quello di sfruttare il livello del filesystem per trasformare i nomi dei file. Da Ubuntu 12.04, esiste un filesystem FUSE che trasforma i nomi dei file in nomi supportati dal VFAT di Windows: fuse-posixovl
.
sudo mount.posixovl /media/sdb1
chown guillaume /media/sdb1
rsync -au ~/mail /media/sbd1/
O per evitare di richiedere l'accesso come root:
mkdir ~/mnt
/sbin/mount.posixovl -S /media/sdb1 ~/mnt
rsync -au ~/mail ~/mnt/
I caratteri nei nomi di file che VFAT non accetta sono codificati come %(XX)dove XXsono cifre esadecimali. A partire da POSIXovl 1.2.20120215, fai attenzione che un nome di file come %(3A)è codificato come se stesso e verrà decodificato come :, quindi c'è un rischio di collisione se hai nomi di file contenenti sottostringhe del modulo %(XX).
Attenzione che POSIXovl non gestisce i nomi dei file troppo lunghi. Se il nome codificato non può contenere 255 caratteri, il file non può essere memorizzato.
POSIXovl memorizza le autorizzazioni e la proprietà unix nei file chiamati .pxovl.FILENAME.
Il seguente script bash ≥4 viene copiato ~/mail/foo:barin /media/usb99/mail/foo_bar, e allo stesso modo per tutti i file in ~/mail. I file già esistenti nella struttura di destinazione e che non sono più vecchi dell'origine vengono ignorati.
#!/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
Questo script funziona con zsh con piccole modifiche: sostituisci shopt -s dotglob globstarcon setopt dot_globe [[ $target -ot $source ]]con [[ ! -e $target || $target -ot $source ]].
Ecco una zsh a due righe (tre se conti i caricamenti automatici). È più corto, ma abbastanza avanzato e non molto leggibile.
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
zargslinea equivale a mkdir -p ~/mail/**/*(…), tranne per il fatto che non esploderà se la lunghezza cumulata dei nomi delle directory è troppo lunga. Quella riga crea le directory di destinazione secondo necessità.
~/mail/**/*(/)si espande in tutte le directory in ~/mail(directory solo a causa (/)della fine).
(/e\''…'\')seleziona solo le directory ed esegue ulteriormente il codice all'interno di '...' per trasformare ciascun nome di file, che è memorizzato nella REPLYvariabile.
${${REPLY#$HOME/}//:/_}rimuove il prefisso corrispondente alla directory di origine e cambia :in _.
zmv -C copia ogni file corrispondente al suo primo operando (un modello zsh) al nome del file ottenuto espandendo il suo secondo operando.
-o -pudice di passare -pual cpprogramma di utilità, in modo da preservare i permessi e copiare solo i file aggiornati. (Potremmo dire a zsh di eseguire il controllo degli aggiornamenti; sarebbe un po 'più veloce ma anche più criptico.)
(.)seleziona solo file regolari. -Qdice che questo deve essere analizzato come un qualificatore glob e non come una .tra parentesi che indica una sottoespressione.
$1e $2nel testo di sostituzione corrispondono le espressioni tra parentesi (**/)e *. ( **perde il suo significato speciale come zero o più livelli di sottodirectory se è tra parentesi, a meno che le parentesi non contengano esattamente **/.)
Inizialmente ho pensato di usare pax , che è uno strumento di archiviazione (qui destinato ad essere utilizzato in modalità pass-through) che ha una funzione di ridenominazione dei file (la sua -sopzione). Tuttavia, le opzioni -se -unon funzionano insieme (la definizione POSIX di pax dice letteralmente che -udeve controllare un file con lo stesso nome nella struttura di destinazione, piuttosto che il nome del file trasformato da -s; l'implementazione di pax in Ubuntu segue le specifiche letteralmente piuttosto che utilmente). È ancora possibile utilizzarlo per creare collegamenti rigidi rinominati, quindi copiare i collegamenti fissi (con rsync -auo pax -rw -pp -u) su altri supporti, ma sembra più un problema di quanto valga la pena.
cd ~/mail
mkdir -p /media/usb99/mail
pax -rw -l -pp -s '!:!_!g' . ../mail.colonless
rsync -au ../mail.colonless/ /media/usb99/mail/