Spostare un file e sostituirlo con un collegamento simbolico


16

Qualcuno può darmi un comando che dovrebbe:

  • sposta un file in una nuova directory
  • e lasciare un collegamento simbolico nella sua posizione precedente verso quello nuovo

Risposte:


19

mvsposta un file e ln -screa un collegamento simbolico, quindi l'attività di base viene eseguita da uno script che esegue questi due comandi:

#!/bin/sh
mv -- "$1" "$2"
ln -s -- "$2" "$1"

Ci sono alcuni avvertimenti. Se il secondo argomento è una directory, mvil file verrà spostato in quella directory, ma ln -sverrà creato un collegamento alla directory anziché al file spostato.

#!/bin/sh
set -e
original="$1" target="$2"
if [ -d "$target" ]; then
  target="$target/${original##*/}"
fi
mv -- "$original" "$target"
ln -s -- "$target" "$original"

Un altro avvertimento è che il primo argomento ln -sè il testo esatto del collegamento simbolico. È relativo alla posizione della destinazione, non alla directory in cui viene eseguito il comando. Se la posizione originale non si trova nella directory corrente e la destinazione non è espressa da un percorso assoluto, il collegamento sarà errato. In questo caso, il percorso deve essere riscritto. In questo caso, creerò un collegamento assoluto (sarebbe preferibile un collegamento relativo, ma è più difficile ottenere il giusto). Questo script presuppone che non si disponga di nomi di file che terminano con un carattere di nuova riga.

#!/bin/sh
set -e
original="$1" target="$2"
if [ -d "$target" ]; then
  target="$target/${original##*/}"
fi
mv -- "$original" "$target"
case "$original" in
  */*)
    case "$target" in
      /*) :;;
      *) target="$(cd -- "$(dirname -- "$target")" && pwd)/${target##*/}"
    esac
esac
ln -s -- "$target" "$original"

Se hai più file, elaborali in un ciclo.

#!/bin/sh
while [ $# -gt 1 ]; do
  eval "target=\${$#}"
  original="$1"
  if [ -d "$target" ]; then
    target="$target/${original##*/}"
  fi
  mv -- "$original" "$target"
  case "$original" in
    */*)
      case "$target" in
        /*) :;;
        *) target="$(cd -- "$(dirname -- "$target")" && pwd)/${target##*/}"
      esac
  esac
  ln -s -- "$target" "$original"
  shift
done

1
Grazie Gilles, per la sceneggiatura e le spiegazioni. Proverò a capirlo!
Yo B.

Questa dovrebbe essere contrassegnata come la risposta giusta
Sridhar Sarnobat il

Per rendere questa risposta ancora più fantastica, rsync --remove-source-filespotrebbe essere più informativo per gli utenti che stanno spostando un file di grandi dimensioni da un disco, il che potrebbe richiedere del tempo.
Sridhar Sarnobat,

Penso che dovresti chiamare sh con -e in modo che si rompa sugli errori, ad esempio se interrompi il comando mv perché esiste già un file
Alex

2

Mettilo nel file .sh e rendilo eseguibile ( chmod +x filename):

#!/bin/bash

mv "$1" "$2"
ln -s "$2" "$1"

Esempio di utilizzo:

./test.sh asdf otherdir/asdf

Si noti che ciò non comporta controlli di sicurezza, ecc. A seconda di quanto sia complessa l'attività, ciò potrebbe essere sufficiente.


Grazie Matteo, funziona perfettamente se applicato su un file. Ma si può aiutarmi a generalizzare questo per due directory come questo: ./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf. Il *non sembra di lavorare con il vostro test.sh. Hai una soluzione? Grazie
Yo B.

2
@kadok Lo script di MatthewRock funziona solo per un singolo file e la destinazione deve essere un percorso assoluto, altrimenti l'origine deve trovarsi nella directory corrente.
Gilles 'SO- smetti di essere malvagio' il

Inoltre, non funzionerà se $ 1 è un file ma $ 2 è una directory.
Sridhar Sarnobat,

0

In genere utilizzo questa funzione a una riga:

function ml() { mkdir -p "$(dirname "$1")" && rsync -aP --no-links "$1" "$2" && ln -sf "$2" "$1" }

L'utilizzo è simile a mv o cp:

ml old_file target_dir/new_file_name

Abbattendo:

  • mkdir -p "$(dirname "$1")" - crea la directory di destinazione se non esiste già
    • dirname "$1" - ottieni il componente directory del percorso (elimina il nome file)
  • rsync -aP --no-links "$1" "$2"- copia il file sulla destinazione. Sostituiscilo con mv "$1" "$2"se entrambi i file si trovano sullo stesso filesystem per prestazioni migliori.
    • -a- preservare la proprietà e tutte le altre autorizzazioni. È possibile ottimizzare questo per preservare solo i componenti desiderati.
    • -P - mostra progressi.
    • --no-links - non copiare i collegamenti - questo significa che puoi eseguire questo comando tutte le volte che vuoi sullo stesso file e non perderai mai il tuo file sovrascrivendo accidentalmente il tuo file di destinazione con un link simbolico a se stesso.
  • ln -sf "$2" "$1" - sovrascrive il vecchio file con un link simbolico al nuovo file
    • -s - usa collegamenti simbolici
    • -f - sovrascrive il vecchio file
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.