Esiste un modo semplice per sostituire tutti i collegamenti simbolici con il file a cui si collegano?
Esiste un modo semplice per sostituire tutti i collegamenti simbolici con il file a cui si collegano?
Risposte:
Per alcune definizioni di "facile":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Esegui questo script con i nomi dei collegamenti come argomenti, ad esempio tramite find . -type l -exec /path/tos/script {} +
"$var"
a "${var}"
è un noop in sh / bash. Ho rimosso l'uno bashism ( [[
), il resto è compatibile con POSIX sh.
cp
di un file temporaneo nella stessa directory, quindi di mv -f
quel file temporaneo nell'originale. Questo dovrebbe evitare problemi come persone che tengono premuto Ctrl-C
o che il filesystem si riempie tra i comandi rm
e cp
(impedendo così anche al nuovo ln
di funzionare). I nomi di file temporanei sono facili da individuare ls -a
per una successiva pulizia, se necessario.
abstarget=$(readlink -f "$link")
il case case , ma potrebbe essere stato motivi di portabilità.
Potrebbe essere più semplice usare tar per copiare i dati in una nuova directory.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Potresti usare qualcosa del genere
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
è la soluzione più semplice
cp
implementazioni copieranno le directory.
Se ti ho capito correttamente, la -L
bandiera del cp
comando dovrebbe fare esattamente quello che vuoi.
Basta copiare tutti i collegamenti simbolici e li sostituirà con i file a cui puntano.
cp -L files tmp/ && rm files && cp tmp/files .
se chiarisci, probabilmente aiuterai più persone ...
"facile" sarà una tua funzione, molto probabilmente.
Probabilmente scriverei uno script che utilizza l'utilità della riga di comando "trova" per trovare file collegati simbolicamente, quindi chiama rm e cp per rimuovere e sostituire il file. Probabilmente faresti bene ad avere anche l'azione chiamata da find check che c'è abbastanza spazio libero prima di spostare anche il link sym.
Un'altra soluzione potrebbe essere quella di montare il file system in questione attraverso qualcosa che nasconda i collegamenti sym (come samba), quindi copiare tutto da quello. Ma in molti casi, qualcosa del genere introdurrebbe altri problemi.
Una risposta più diretta alla tua domanda è probabilmente "sì".
Modifica: secondo la richiesta di informazioni più specifiche. Secondo la pagina man di find , questo comando elencherà tutti i file del link sym in una profondità di 2 directory, da /:
find / -maxdepth 2 -type l -print
( questo è stato trovato qui )
Per trovare trovare per eseguire qualcosa su trovarlo:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Credo che chiamerà alcuni script che ho appena creato e passerà il nome del file che hai appena trovato. In alternativa, è possibile acquisire l'output di ricerca su file (utilizzare "trova [blah]> symlink.data", ecc.), Quindi passare quel file a uno script scritto per gestire la copia sull'originale con garbo.
-exec ./ReplaceSymLink.sh {} \;
Questo è l'oneliner che ho usato: supponiamo che tutti i file locali siano collegamenti a un altro file in "sorgente". È possibile affinare la selezione dei file con motivi o "trova". Per favore, capisci prima di usare.
per f in *; do cp --remove-destination source / $ f $ f; fatto
Spero che sia di aiuto
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Farà una copia di ogni file / cartella con collegamento simbolico in <filename>.dereferenced
, che è più sicuro (se meno conveniente) rispetto alla semplice sostituzione diretta. Lo spostamento dei dati copiati nei nomi dei file dei link simbolici viene lasciato come esercizio per il lettore.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
basato su /superuser//a/1301199/499386 di MastroGeppetto
Molte buone risposte lì, ma io da quando stavi cercando qualcosa di facile
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
Ho avuto lo stesso problema con la copia dei link di gwenview quando normalmente ti aspetteresti che segua il link e copi il file.
Quello che ho fatto per "ripulire" la directory seguendo tutti i collegamenti e copiando tutti i file puntati nella directory, è stato creare una directory scratch, eseguire ad es.
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
questo è troppo pericoloso per essere inserito in uno script in quanto non vi è alcun controllo ma ha risolto il mio problema.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Ho fatto una versione di una riga, dal momento che il mio web-hotel non ha permesso script bash e ha funzionato bene per me:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0