Przenieś plik i zastąp go dowiązaniem symbolicznym


16

Czy ktoś może mi wydać polecenie, które:

  • przenieś plik do nowego katalogu
  • i pozostaw łącze symboliczne w starej lokalizacji w kierunku nowej

Odpowiedzi:


19

mvprzenosi plik i ln -stworzy dowiązanie symboliczne, więc podstawowe zadanie wykonuje skrypt, który wykonuje te dwa polecenia:

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

Jest kilka zastrzeżeń. Jeśli drugim argumentem jest katalog, mvprzenosi plik do tego katalogu, ale ln -stworzy łącze do katalogu, a nie do przeniesionego pliku.

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

Innym zastrzeżeniem jest to, że pierwszym argumentem ln -sjest dokładny tekst dowiązania symbolicznego. Jest to zależne od położenia celu, a nie katalogu, w którym polecenie jest wykonywane. Jeśli oryginalnej lokalizacji nie ma w bieżącym katalogu, a cel nie jest wyrażony przez ścieżkę bezwzględną, link będzie niepoprawny. W takim przypadku ścieżka musi zostać przepisana. W takim przypadku utworzę link bezwzględny (preferowany byłby link względny, ale trudniej jest go poprawnie uzyskać). Ten skrypt zakłada, że ​​nie masz nazw plików, które kończą się znakiem nowej linii.

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

Jeśli masz wiele plików, przetwarzaj je w pętli.

#!/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
Dzięki Gilles za scenariusz i wyjaśnienia. Spróbuję to zrozumieć!
Yo B.

Należy to zaznaczyć jako właściwą odpowiedź
Sridhar Sarnobat,

Aby uczynić tę odpowiedź jeszcze bardziej niesamowitą, rsync --remove-source-filesmoże być bardziej pouczająca dla użytkowników, którzy przenoszą duży plik z dysku, co może zająć trochę czasu.
Sridhar Sarnobat

Myślę, że powinieneś wywołać sh za pomocą -e, aby zepsuło się ono na błędy, na przykład, jeśli zatrzymasz polecenie mv, ponieważ plik już istnieje
Alex

2

Umieść to w pliku .sh i uczyń go wykonywalnym ( chmod +x filename):

#!/bin/bash

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

Przykład użycia:

./test.sh asdf otherdir/asdf

Pamiętaj, że nie wymaga to kontroli bezpieczeństwa itp. W zależności od stopnia złożoności zadania może to być wystarczające.


Dziękuję Matthew, to działa idealnie, gdy zastosuje się na jednym pliku. Ale możesz mi pomóc to uogólnienie do dwóch katalogów, takich jak ten: ./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf. *Nie wydają się być pracy z test.sh. Czy masz obejście? Thx
Yo B.

2
@kadok Skrypt MatthewRock działa tylko dla jednego pliku, a celem musi być ścieżka bezwzględna, w przeciwnym razie źródło musi znajdować się w bieżącym katalogu.
Gilles „SO- przestań być zły”

Ponadto nie będzie działać, jeśli $ 1 to plik, ale $ 2 to katalog.
Sridhar Sarnobat,

0

Ogólnie używam tej funkcji jednowierszowej:

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

Użycie jest podobne do mv lub cp:

ml old_file target_dir/new_file_name

Podział:

  • mkdir -p "$(dirname "$1")" - utwórz katalog docelowy, jeśli jeszcze nie istnieje
    • dirname "$1" - pobierz komponent katalogu ścieżki (usuń nazwę pliku)
  • rsync -aP --no-links "$1" "$2"- skopiuj plik do miejsca docelowego. Zastąp to, mv "$1" "$2"jeśli oba pliki znajdują się w tym samym systemie plików, aby uzyskać lepszą wydajność.
    • -a- zachować własność i wszystkie inne uprawnienia. Możesz to dostroić, aby zachować tylko te elementy, które chcesz.
    • -P - pokaż postęp.
    • --no-links - nie kopiuj linków - oznacza to, że możesz uruchomić tę komendę tyle razy, ile chcesz na tym samym pliku, i nigdy nie stracisz pliku, przypadkowo zastępując plik docelowy dowiązaniem symbolicznym do siebie.
  • ln -sf "$2" "$1" - nadpisz stary plik dowiązaniem symbolicznym do nowego pliku
    • -s - używaj dowiązań symbolicznych
    • -f - nadpisz stary plik
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.