Mover um arquivo e substituí-lo por um link simbólico

12

Alguém pode me dar um comando que:

  • move um arquivo para um novo diretório
  • e deixar um link simbólico em seu local antigo em direção ao novo
por Yo B. 07.09.2015 / 11:31

3 respostas

15

mv move um arquivo e ln -s cria um link simbólico, então a tarefa básica é realizada por um script que executa esses dois comandos:

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

Existem algumas ressalvas. Se o segundo argumento for um diretório, então mv moverá o arquivo para esse diretório, mas ln -s criaria um link para o diretório em vez de para o arquivo movido.

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

Outra ressalva é que o primeiro argumento para ln -s é o texto exato do link simbólico. É relativo ao local do alvo, não ao diretório onde o comando é executado. Se o local original não estiver no diretório atual e o destino não for expresso por um caminho absoluto, o link estará incorreto. Nesse caso, o caminho precisa ser reescrito. Nesse caso, criarei um link absoluto (um link relativo seria preferível, mas é mais difícil acertar). Este script assume que você não tem nomes de arquivo que terminam em um caractere de nova linha.

#!/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 você tiver vários arquivos, processe-os em um loop.

#!/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
    
por 08.09.2015 / 02:38
2

Coloque isso no arquivo .sh e torne-o executável ( chmod +x filename ):

#!/bin/bash

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

Exemplo de uso:

./test.sh asdf otherdir/asdf

Observe que isso não faz verificações de segurança, etc. Dependendo de quão complexa é a sua tarefa, isso pode ser suficiente.

    
por 07.09.2015 / 11:40
0

Eu geralmente uso a função de uma linha:

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

O uso é semelhante a mv ou cp:

ml old_file target_dir/new_file_name

Quebrando:

  • mkdir -p "$(dirname "$1")" - cria o diretório de destino, se ele ainda não existir
    • dirname "$1" - obtém o componente de diretório do caminho (tira o nome do arquivo)
  • rsync -aP --no-links "$1" "$2" - copia o arquivo para o destino. Substitua isto por mv "$1" "$2" se ambos os arquivos estiverem no mesmo sistema de arquivos para melhor desempenho.
    • -a - preserve a propriedade e todas as outras permissões. Você pode ajustar isso para preservar apenas os componentes desejados.
    • -P - mostra o progresso.
    • --no-links - não copia links - isso significa que você pode executar este comando quantas vezes quiser no mesmo arquivo, e você nunca perderá seu arquivo substituindo acidentalmente seu arquivo de destino por um symlink para si mesmo.
  • ln -sf "$2" "$1" - sobrescreve o arquivo antigo com um link simbólico para o novo arquivo
    • -s - use links simbólicos
    • -f - sobrescreve o arquivo antigo
por 15.06.2018 / 00:00