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 XX
sono 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:bar
in /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 globstar
con setopt dot_glob
e [[ $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
zargs
linea 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 REPLY
variabile.
${${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 -pu
dice di passare -pu
al cp
programma 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. -Q
dice che questo deve essere analizzato come un qualificatore glob e non come una .
tra parentesi che indica una sottoespressione.
$1
e $2
nel 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 -s
opzione). Tuttavia, le opzioni -s
e -u
non funzionano insieme (la definizione POSIX di pax dice letteralmente che -u
deve 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 -au
o 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/