Можете ли вы изменить то, на что указывает символическая ссылка после ее создания?
Предоставляет ли какая-либо операционная система механизм (системный вызов, а не программа командной строки), чтобы изменить путь, на который ссылается символическая ссылка (символическая ссылка), - иначе, чем отключение старого и создание нового?
В стандарте POSIX нет. Solaris 10 - нет. MacOS X 10.5 (Leopard) нет. (Я уверен, что ни AIX, ни HP-UX не делают этого. Судя по этому списку системные вызовы Linux, Linux не имеет такой системы вызовите.)
Есть ли что-нибудь, что делает?
(Я ожидаю, что ответ будет "Нет".)
Так как доказательство отрицательного жестко, реорганизуйте вопрос.
Если вы знаете, что некоторая (Unix-подобная) операционная система, которая еще не указана, не имеет системного вызова для перезаписи значения символической ссылки (строка, возвращаемая readlink()
), не удаляя старую символическую ссылку и создавая новую, пожалуйста добавьте его - или их - в ответ.
Ответы
Ответ 1
AFAIK, нет, вы не можете. Вы должны удалить его и заново создать. Собственно, вы можете перезаписать символическую ссылку и, таким образом, обновить имя пути, на которое она ссылается:
$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 pascal pascal 8 2009-09-23 17:12 test -> .profile
EDIT. Как указывал OP в комментарии, использование опции --force
сделает ln
выполнить системный вызов unlink()
до symlink()
. Ниже выведено значение strace
в моем linux-окне, подтверждающее это:
$ strace -o /tmp/output.txt ln -s -f .bash_aliases test
$ grep -C3 ^unlink /tmp/output.txt
lstat64("test", {st_mode=S_IFLNK|0777, st_size=7, ...}) = 0
stat64(".bash_aliases", {st_mode=S_IFREG|0644, st_size=2043, ...}) = 0
symlink(".bash_aliases", "test") = -1 EEXIST (File exists)
unlink("test") = 0
symlink(".bash_aliases", "test") = 0
close(0) = 0
close(1) = 0
Итак, я думаю, что окончательный ответ "нет".
EDIT: следующее копируется из ответа Арто Бендикена на unix.stackexchange.com, около 2016 года.
Этот может выполняться атомарно с помощью rename(2)
, сначала создавая новую символическую ссылку под временным именем, а затем чисто переписывая старую символическую ссылку за один раз. Поскольку страница указывает:
Если newpath ссылается на символическую ссылку, ссылка будет перезаписана.
В оболочке вы сделаете это с помощью mv -T
следующим образом:
$ mkdir a b
$ ln -s a z
$ ln -s b z.new
$ mv -T z.new z
Вы можете strace
выполнить последнюю команду, чтобы убедиться, что она действительно использует rename(2)
под капотом:
$ strace mv -T z.new z
lstat64("z.new", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
lstat64("z", {st_mode=S_IFLNK|0777, st_size=1, ...}) = 0
rename("z.new", "z") = 0
Обратите внимание, что в приведенном выше примере оба mv -T
и strace
зависят от Linux.
В FreeBSD поочередно используйте mv -h
.
Примечание редактора: Вот как Капистрано это делал уже много лет, начиная с ~ 2.15. См. этот запрос на растяжение.
Ответ 2
Да, вы можете!
$ ln -sfn source_file_or_directory_name softlink_name
Ответ 3
Нет необходимости явно отключать старую символическую ссылку. Вы можете сделать это:
ln -s newtarget temp
mv temp mylink
(или используйте эквивалентные вызовы symlink и rename). Это лучше, чем прямое отключение, потому что переименование является атомарным, поэтому вы можете быть уверены, что ссылка всегда будет указывать на старую или новую цель. Однако это не приведет к повторному использованию исходного индексного дескриптора.
В некоторых файловых системах мишень символической ссылки сохраняется в самом дескрипторе (вместо списка блоков), если он достаточно короткий; это определяется во время создания.
Что касается утверждения о том, что фактический владелец и группа несущественны, symlink (7) в Linux говорит, что есть случай, когда он значителен
Владелец и группа существующей символической ссылки могут быть изменены с помощью lchown (2). Единственный раз, когда владение символической ссылкой имеет значение когда ссылка удаляется или переименовывается в каталог с липкой бит (см. stat (2)).
Последними метками времени доступа и последней модификацией символической ссылки могут быть изменено с помощью utimensat (2) или lutimes (3).
В Linux права на символическую ссылку не используются ни в каких операциях; разрешения всегда 0777 (чтение, запись и выполнение для всех пользователей категорий) и не может быть изменен.
Ответ 4
Не отменил бы его и создав новый, все равно сделайте то же самое в конце?
Ответ 5
Просто предупреждение правильных ответов выше:
Использование метода -f/-force дает риск потерять файл, если вы смешиваете источник и цель:
[email protected]:~/test$ ls -la
total 11448
drwxr-xr-x 2 mbucher www-data 4096 May 25 15:27 .
drwxr-xr-x 18 mbucher www-data 4096 May 25 15:13 ..
-rw-r--r-- 1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
-rw-r--r-- 1 mbucher www-data 7582480 May 25 15:27 otherdata.tar.gz
lrwxrwxrwx 1 mbucher www-data 11 May 25 15:26 thesymlink -> data.tar.gz
[email protected]:~/test$
[email protected]:~/test$ ln -s -f thesymlink otherdata.tar.gz
[email protected]:~/test$
[email protected]:~/test$ ls -la
total 4028
drwxr-xr-x 2 mbucher www-data 4096 May 25 15:28 .
drwxr-xr-x 18 mbucher www-data 4096 May 25 15:13 ..
-rw-r--r-- 1 mbucher www-data 4109466 May 25 15:26 data.tar.gz
lrwxrwxrwx 1 mbucher www-data 10 May 25 15:28 otherdata.tar.gz -> thesymlink
lrwxrwxrwx 1 mbucher www-data 11 May 25 15:26 thesymlink -> data.tar.gz
Конечно, это предназначено, но обычно происходят ошибки. Таким образом, удаление и перестроение символической ссылки - это немного больше работы, но также и сбережение:
[email protected]:~/test$ rm thesymlink && ln -s thesymlink otherdata.tar.gz
ln: creating symbolic link `otherdata.tar.gz': File exists
который, по крайней мере, сохраняет мой файл.
Ответ 6
На всякий случай это помогает: есть способ редактировать символическую связь с полуночным командиром (mc).
Команда меню (по-французски на моем интерфейсе mc):
Fichier / Éditer le lien symbolique
который может быть переведен на:
File / Edit symbolic link
Ярлык: C-x C-s
Может быть, он внутренне использует команду ln --force
, я не знаю.
Теперь я пытаюсь найти способ редактировать сразу множество символических ссылок (это как я сюда приехал).
Ответ 7
Технически нет встроенной команды для редактирования существующей символической ссылки. Его можно легко выполнить с помощью нескольких коротких команд.
Здесь немного bash/zsh function Я написал для обновления существующей символической ссылки:
# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with
# -----------------------------------------
function edit-symlink () {
if [ -z "$1" ]; then
echo "Name of symbolic link you would like to edit:"
read LINK
else
LINK="$1"
fi
LINKTMP="$LINK-tmp"
if [ -z "$2" ]; then
echo "Full destination path to update existing symlink with:"
read DEST
else
DEST="$2"
fi
ln -s $DEST $LINKTMP
rm $LINK
mv $LINKTMP $LINK
printf "Updated $LINK to point to new destination -> $DEST"
}