Ich konvertiere einen großen Dateisatz von einem Dateisystem mit einer hohen _PC_LINK_MAX
(maximale Anzahl von Hardlinks pro Inode) auf ein niedrigeres.
Insbesondere spiele ich mit Amazon EFS herum, das wie angegeben ein Maximum von 175 hatHier.
Daher hätte ich als Eingabe gerne einen Satz von Dateien mit Linkzahlen von bis zu 250, die neu angeordnet wurden, sodass die Inodes so aufgeteilt werden, dass das Maximum bei jeweils 100 Links liegt.
Gibt es eine clevere Aufrufmöglichkeit, hardlink
die das kann? Oder vielleicht eine Option, rsync -aH
die cp -a
helfen kann?
...ansonsten ist etwas Hackerei angesagt...
Antwort1
Die Situation ist knifflig. Stellen Sie sich vor, die maximale Anzahl an Links beträgt 5 und Sie haben 12 Dateien,
a01
die alle fest miteinander verknüpft sind. Sie müssen und und a12
aufteilen , wobei und usw. immer noch fest miteinander verknüpft sind, aber nicht mit .a01..a05
a06..a10
a11..a12
a06
a07
a01
Hier ist ein Bash-Skript, rsync
das in einem Beispiel-Quellverzeichnis ( src=/usr/libexec/git-core/
) auf meinem System läuft, das 110 Hardlinks hat. Es simuliert eine maximale Anzahl von 50 Links ( max
) im Zielverzeichnis realdest
durch die Funktion sim
. In einem realen Fall würden Sie einfach diezu viele LinksFehler und verwenden Sie diese Funktion nicht.
Nach dem anfänglichen normalen rsync (mit Fehlern) wird die Liste der fehlenden Dateien erstellt rsync -ni
, indem die Dateinamen in der Funktion calctodo
in extrahiert werden /tmp/todo
.
Es gibt dann eine Schleife, in der wir rsync
die fehlenden Dateien wieder ignorierenzu viele LinksFehler (die auftreten würden, wenn Sie mehr als 2*175
Links im Originalverzeichnis hätten). Die erfolgreich erstellten Dateien werden untereinander fest verknüpft. Die neue Liste der fehlenden Dateien wird berechnet. Dies wird wiederholt, bis keine Dateien mehr vorhanden sind.
src=/usr/libexec/git-core/
realdest=/tmp/realdest
#rm -fr "$realdest"
max=50
sim(){
find ${1?} -links +$max |
sed "1,${max}d" |
xargs --no-run-if-empty rm
}
calctodo(){
sed -n '/^hf/{ s/[^ ]* //; s/ =>.*//; p }' >/tmp/todo
}
rsync -aHR "$src" "$realdest"; sim "$realdest"
rsync -niaHR "$src" "$realdest" | calctodo
while [ -s /tmp/todo ]
do mv /tmp/todo /tmp/todo.old
rsync -aHR --files-from=/tmp/todo.old / "$realdest"; sim "$realdest"
rsync -niaHR --files-from=/tmp/todo.old / "$realdest" | calctodo
done
Möglicherweise müssen Sie dies überarbeiten, wenn Sie Dateinamen mit „==“, Zeilenumbrüchen usw. haben.
Beachten Sie, dass Sie die maximale Anzahl von Links, die ein Dateisystem unterstützt, ermitteln können, indem Sie
getconf LINK_MAX /some/directory