Можете ли вы изменить то, на что указывает символическая ссылка после ее создания?

Предоставляет ли какая-либо операционная система механизм (системный вызов, а не программа командной строки), чтобы изменить путь, на который ссылается символическая ссылка (символическая ссылка), - иначе, чем отключение старого и создание нового?

В стандарте 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"
}