Перемістіть файл і замініть його символьним посиланням


16

Чи може хтось дати мені команду, яка б:

  • перемістити файл у новий каталог
  • і залиште символьне посилання на старому місці до нового

Відповіді:


19

mvпереміщує файл і ln -sстворює символічне посилання, тому основне завдання виконується сценарієм, який виконує ці дві команди:

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

Існує кілька застережень. Якщо другий аргумент - це каталог, тоді mvвін перемістить файл у цей каталог, але ln -sстворив би посилання на каталог, а не на переміщений файл.

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

Ще одне застереження полягає в тому, що перший аргумент ln -s- це точний текст символічного посилання. Це відносно розташування цілі, а не до каталогу, де виконується команда. Якщо оригінального місця розташування немає у поточному каталозі, а ціль не виражена абсолютним шляхом, посилання буде неправильним. У цьому випадку шлях потрібно переписати. У такому випадку я створять абсолютне посилання (переважніше відносне посилання, але складніше правильно вийти). Цей сценарій передбачає, що у вас немає імен файлів, які закінчуються символом нового рядка.

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

Якщо у вас кілька файлів, обробіть їх у циклі.

#!/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
Дякую Жиллу, за сценарій та пояснення. Я спробую це зрозуміти!
Йо Б.

Це слід позначити як правильну відповідь
Шрідхар Сарнобат

Щоб зробити цю відповідь ще приголомшливішою, rsync --remove-source-filesможе бути більш інформативною для користувачів, які переміщують великий файл з диска, що може зайняти деякий час.
Шрідхар Сарнобат

Я думаю, вам слід зателефонувати sh з -e, щоб воно порушило помилки, наприклад, якщо ви зупините команду mv, оскільки файл уже існує
Alex

2

Помістіть цей файл у .sh та зробіть його виконуваним ( chmod +x filename):

#!/bin/bash

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

Приклад використання:

./test.sh asdf otherdir/asdf

Зауважте, що це не проводить перевірок безпеки і т. Д. Залежно від того, наскільки складним є ваше завдання, цього може бути достатньо.


Дякую Метью, це прекрасно працює, коли застосовується до одного файлу. Але ви можете мені допомогти узагальнюючи це двох каталогів , як це: ./test.sh .mozila/firefox/zotero/*/*.pdf MyBbliography/*.pdf. Схоже, *це не працює з вашими test.sh. У вас є рішення? Thx
Yo B.

2
Сценарій @kadok MatthewRock працює лише для одного файлу, а ціль повинен бути абсолютним шляхом, інакше джерело повинно бути в поточному каталозі.
Жил 'ТАК - перестань бути злим'

Крім того, він не працюватиме, якщо $ 1 - це файл, але $ 2 - це каталог.
Шрідхар Сарнобат

0

Я зазвичай використовую цю однолінійну функцію:

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

Використання схоже на mv або cp:

ml old_file target_dir/new_file_name

Розбийте його:

  • mkdir -p "$(dirname "$1")" - створити каталог призначення, якщо він ще не існує
    • dirname "$1" - отримати компонент каталогів шляху (зніміть ім'я файлу)
  • rsync -aP --no-links "$1" "$2"- скопіюйте файл до місця призначення. Замініть його , mv "$1" "$2"якщо обидва файли знаходяться на одній і тій же файлової системи для кращої продуктивності.
    • -a- зберегти право власності та всі інші дозволи. Ви можете налаштувати це лише для збереження потрібних компонентів.
    • -P - показати прогрес.
    • --no-links - не копіюйте посилання - це означає, що ви можете виконувати цю команду стільки разів, скільки вам потрібно, в одному файлі, і ви ніколи не втратите файл, випадково перезаписавши цільовий файл із символьним посиланням на себе.
  • ln -sf "$2" "$1" - перезаписати старий файл із символьним посиланням на новий файл
    • -s - використовувати символічні посилання
    • -f - перезаписати старий файл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.