Questo può effettivamente essere fatto atomicamente con rename(2)
, creando prima il nuovo collegamento simbolico con un nome temporaneo e quindi sovrascrivendo in modo pulito il vecchio collegamento simbolico in una volta sola. Come afferma la pagina man:
Se nuovopercorso fa riferimento a un collegamento simbolico il collegamento verrà sovrascritto.
Nella shell, lo faresti con mv -T
come segue:
$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z
Puoi strace
l'ultimo comando per assicurarsi che stia effettivamente usando rename(2)
sotto il cofano:
$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z") = 0
Nota che in quanto sopra, entrambi mv -T
e strace
sono specifici di Linux.
Su FreeBSD, usa mv -h
alternativamente.
Riprendendo da dove Arto ha lasciato qui, questo è del tutto possibile, anche senza mv -T
, devi solo creare un nuovo collegamento simbolico con lo stesso nome della directory di destinazione e mv
nella directory principale del tuo target:
mkdir -p tmp/real_dir1 tmp/real_dir2
touch tmp/real_dir1/a tmp/real_dir2/a
# start with ./target_dir pointing to tmp/real_dir1
ln -s tmp/real_dir1 target_dir
# create a symlink named target_dir in tmp, pointing to real_dir2
ln -sf tmp/real_dir2 tmp/target_dir
# atomically mv it into ./ replacing ./target_dir
mv tmp/target_dir ./
Esempio di codice preso tramite (http://axialcorps.wordpress.com/2013/07/03/atomically-replacing-files-and-directories/)
Hai provato ln -snf
?
L'opzione -n
sovrascrive la destinazione anziché scrivere sotto di essa quando la destinazione è un collegamento simbolico a una directory.
Saluti