Am einfachsten ist es, die Dateisystemebene zu nutzen, um die Dateinamen zu transformieren. Seit Ubuntu 12.04 gibt es ein FUSE- Dateisystem, das Dateinamen in Namen umwandelt, die von Windows VFAT unterstützt werden: fuse-posixovl .
sudo mount.posixovl /media/sdb1
chown guillaume /media/sdb1
rsync -au ~/mail /media/sbd1/
Oder um zu vermeiden, dass Root-Zugriff erforderlich ist:
mkdir ~/mnt
/sbin/mount.posixovl -S /media/sdb1 ~/mnt
rsync -au ~/mail ~/mnt/
Zeichen in Dateinamen , dass VFAT nicht akzeptiert codiert sind , als %(XX)
wo XX
sind hexadezimale Ziffern. Achten Sie ab POSIXovl 1.2.20120215 darauf, dass ein Dateiname wie derselbe als solcher %(3A)
codiert und als solcher decodiert wird. Daher :
besteht Kollisionsgefahr, wenn Sie Dateinamen haben, die Teilzeichenfolgen des Formulars enthalten %(XX)
.
Beachten Sie, dass POSIXovl mit zu langen Dateinamen nicht zurechtkommt. Wenn der verschlüsselte Name nicht in 255 Zeichen passt, kann die Datei nicht gespeichert werden.
POSIXovl speichert Unix-Berechtigungen und -Eigentum in den aufgerufenen Dateien .pxovl.FILENAME
.
Die folgenden bash ≥4 Skript kopiert ~/mail/foo:bar
zu/media/usb99/mail/foo_bar
und für alle Dateien unter~/mail
. Dateien, die bereits in der Zielstruktur vorhanden sind und nicht älter als die Quelle sind, werden übersprungen.
#!/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
Dieses Skript funktioniert unter zsh mit geringfügigen Änderungen: Ersetzen shopt -s dotglob globstar
durchsetopt dot_glob
und [[ $target -ot $source ]]
durch [[ ! -e $target || $target -ot $source ]]
.
Hier ist ein Zsh-Two-Liner (drei, wenn Sie die Autoloads zählen). Es ist kürzer, aber ziemlich weit fortgeschritten und wenig lesbar.
autoload zargs zmv
zargs -- ~/mail/**/*(/e\''REPLY=/media/usb99/${${REPLY#$HOME/}//:/_}'\') -- mkdir -p --
zmv -C -Q -o -pu '~/mail/(**/)(*)(.)' '/media/usb99/mail/${1//:/_}${2//:/_}'
- Das
zargs
Zeile ist äquivalent zu mkdir -p ~/mail/**/*(…)
, außer dass sie nicht bombardiert wird, wenn die kumulierte Länge der Verzeichnisnamen zu lang ist. Diese Zeile erstellt die Zielverzeichnisse nach Bedarf.
~/mail/**/*(/)
Erweitert alle Verzeichnisse unter ~/mail
(Verzeichnisse nur aufgrund der (/)
am Ende).
(/e\''…'\')
Wählt nur Verzeichnisse aus und führt den Code innerhalb von '…' weiter aus, um jeden in der REPLY
Variablen gespeicherten Dateinamen zu transformieren .
${${REPLY#$HOME/}//:/_}
Entfernt das Präfix, das dem Quellverzeichnis entspricht, und ändert es :
zu _
.
zmv -C
kopiert jede Datei, die ihrem ersten Operanden (einem zsh-Muster) entspricht, in den Dateinamen, der durch Erweitern ihres zweiten Operanden erhalten wird.
-o -pu
sagt an -pu
das cp
Dienstprogramm übergeben, um Berechtigungen zu erhalten und nur aktualisierte Dateien zu kopieren. (Wir könnten zsh anweisen, die Update-Prüfung durchzuführen. Sie wäre etwas schneller, aber noch kryptischer.)
(.)
Wählt nur normale Dateien aus. -Q
gibt an, dass dies als Glob-Qualifikationsmerkmal analysiert werden soll und nicht als .
Klammer, die einen Unterausdruck angibt.
$1
und $2
stimmen im Ersetzungstext mit den Ausdrücken in Klammern (**/)
und überein *
. ( **
Verliert seine spezielle Bedeutung als null oder mehr Unterverzeichnisebenen, wenn es in Klammern steht, es sei denn, die Klammern enthalten genau **/
.)
Ursprünglich dachte ich an die Verwendung von pax , einem Archivierungstool (hier für den Passthrough-Modus vorgesehen) mit einer Funktion zum Umbenennen von Dateien ( -s
optional). Die Optionen -s
und -u
funktionieren jedoch nicht zusammen (die POSIX-Definition von pax besagt wörtlich, dass -u
eine Datei mit demselben Namen im Zielbaum geprüft werden muss und nicht der von transformierte Dateiname -s
; die pax-Implementierung in Ubuntu folgt der Spezifikation wörtlich und nicht nützlich). Es ist immer noch möglich, damit umbenannte Hardlinks zu erstellen und die Hardlinks dann (mit rsync -au
oder pax -rw -pp -u
) auf die anderen Medien zu kopieren , aber es bereitet mehr Mühe als es wert ist.
cd ~/mail
mkdir -p /media/usb99/mail
pax -rw -l -pp -s '!:!_!g' . ../mail.colonless
rsync -au ../mail.colonless/ /media/usb99/mail/