web-dev-qa-db-fra.com

Déplacez un fichier et remplacez-le par un lien symbolique

Quelqu'un peut-il me donner une commande qui ferait:

  • déplacer un fichier vers un nouveau répertoire
  • et laisser un lien symbolique dans son ancien emplacement vers son nouveau
16
Yo B.

mv déplace un fichier et ln -s Crée un lien symbolique, la tâche de base est donc accomplie par un script qui exécute ces deux commandes:

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

Il y a quelques mises en garde. Si le deuxième argument est un répertoire, alors mv déplacerais le fichier dans ce répertoire, mais ln -s créerait un lien vers le répertoire plutôt que dans le fichier déplacé.

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

Une autre mise en garde est que le premier argument à ln -s est le texte exact du lien symbolique. Il est relatif à l'emplacement de la cible et non au répertoire où la commande est exécutée. Si l'emplacement d'origine n'est pas dans le répertoire actuel et que la cible n'est pas exprimée par un chemin absolu, le lien sera incorrect. Dans ce cas, le chemin doit être réécrit. Dans ce cas, je vais créer un lien absolu (un lien relatif serait préférable, mais il est plus difficile de se faire bien). Ce script suppose que vous n'avez pas de noms de fichiers terminés par un personnage nouveau.

#!/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"

Si vous avez plusieurs fichiers, traitez-les dans une boucle.

#!/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

Mettez ceci dans le fichier .sh et faites-le exécuter (chmod +x filename):

#!/bin/bash

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

Exemple d'utilisation:

./test.sh asdf otherdir/asdf

Notez que cela ne fait aucun contrôle de sécurité, etc. En fonction de la complexité de votre tâche, cela pourrait suffire.

2
MatthewRock

J'utilise généralement la cette fonction d'une ligne:

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

L'utilisation est similaire à MV ou au CP:

ml old_file target_dir/new_file_name

Le briser:

  • mkdir -p "$(dirname "$1")" - Créez le répertoire de destination s'il n'existe pas déjà
    • dirname "$1" - Obtenez le composant Directory du chemin (Strip the FileName)
  • rsync -aP --no-links "$1" "$2" - Copiez le fichier sur la destination. Remplacez ceci par mv "$1" "$2" Si les deux fichiers sont sur le même système de fichiers pour une meilleure performance. [.____]
    • -a - préserver la propriété et toutes les autres autorisations. Vous pouvez synchroniser cela pour conserver uniquement les composants souhaités.
    • -P - montrer des progrès.
    • --no-links - Ne copiez pas de liens - Cela signifie que vous pouvez exécuter cette commande autant de fois que vous le souhaitez sur le même fichier et que vous ne perdrez jamais votre fichier en écrasant accidentellement votre fichier de destination avec un symbole symbolique. à lui-même.
  • ln -sf "$2" "$1" - écrasez l'ancien fichier avec un lien symbolique vers le nouveau fichier [.____]
    • -s - Utilisez des liens symboliques
    • -f - écrase l'ancien fichier
0
user60561