Відповіді:
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
rsync --remove-source-files
може бути більш інформативною для користувачів, які переміщують великий файл з диска, що може зайняти деякий час.
Помістіть цей файл у .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
Я зазвичай використовую цю однолінійну функцію:
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
- перезаписати старий файл