在创建符号链接之后,是否可以更改它所指向的内容?

是否有任何操作系统提供一种机制(系统调用ーー不是命令行程序)来更改符号链接(symlink)所引用的路径名ーー除了断开旧路径名并创建一个新路径名之外?

POSIX 标准没有。索拉里斯10号没有。MacOS X 10.5(Leopard)则没有。(我相当肯定 AIX 和 HP-UX 都不需要。从 Linux 系统调用的列表来看,Linux 也没有这样的系统调用。)

有没有什么东西能起作用?

(我希望答案是“不”。)


既然证明一个否定是困难的,让我们重新组织这个问题。

如果您知道某些(类似 Unix 的)操作系统没有在不删除旧的符号链接并创建新的符号链接的情况下重写符号链接(由 readlink()返回的字符串)的值的系统调用,请在答案中添加它或它们。

151394 次浏览

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

编辑 : 正如 OP 在注释中指出的,使用 --force选项将使 lnsymlink()之前执行对 unlink()的系统调用。下面,我的 linux 机器上的 strace输出证明了这一点:

$ 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

所以我想最终的答案是“不”。

编辑 : 以下内容摘自大约2016年的 Arto Bendiken 的回答 unix.stackexchange.com。

这个 可以确实是用 rename(2)原子地完成的,首先在一个临时名称下创建新的符号链接,然后一次性完全覆盖旧的符号链接。正如 手册指出的:

如果 Newpath引用一个符号链接,该链接将被覆盖。

在 shell 中,对 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 -Tstrace都是特定于 Linux 的。

在 FreeBSD 上,交替使用 mv -h

编者按: 这是卡皮斯特拉诺多年来的做法,从2.15左右开始。参见 这个请求

解除连接并创建一个新的不会最终做同样的事情吗?

没有必要显式解除旧的符号链接:

ln -s newtarget temp
mv temp mylink

(或使用等效的符号链接和重命名调用)。这比显式断开链接要好,因为重命名是原子的,所以可以确保链接总是指向旧的或新的目标。但是这不会重用原来的 inode。

在某些文件系统上,如果符号链接的目标足够短,它将存储在 inode 本身(代替块列表)中; 这是在创建符号链接时确定的。

关于实际所有者和组是无关紧要的断言,Linux 上的 Symlink (7)表示,有一个案例非常重要:

现有符号链接的所有者和组可以使用 符号链接的所有权唯一重要的时间是 当链接被删除或重命名在具有粘性的目录中时 位设置(见 stat (2))。

符号链接的最后访问和最后修改时间戳可以是 使用 utimensat (2)或 lutimes (3)改变。

在 Linux 上,任何操作都不使用符号链接的权限; 权限始终是0777(所有用户的读、写和执行) 类别) ,并且不能更改。

你可以的!

$ ln -sfn source_file_or_directory_name softlink_name

只是对上述正确答案的一个警告:

使用-f/—— force 方法可能会在混淆源和目标时丢失文件:

mbucher@server2:~/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
mbucher@server2:~/test$
mbucher@server2:~/test$ ln -s -f thesymlink otherdata.tar.gz
mbucher@server2:~/test$
mbucher@server2:~/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

当然,这是有意的,但通常会出现错误。因此,删除和重新构建符号链接需要做更多的工作,但也更省力:

mbucher@server2:~/test$ rm thesymlink && ln -s thesymlink otherdata.tar.gz
ln: creating symbolic link `otherdata.tar.gz': File exists

至少我的档案还在。

以防万一: 有一种方法可以编辑与午夜指挥官(mc)的符号链接。 菜单命令是(在我的 mc 界面上是法语) :

Fichier / Éditer le lien symbolique

可译为:

File / Edit symbolic link

捷径是 C-x C-s

也许它内部使用 ln --force命令,我不知道。

现在,我试图找到一种方法来一次编辑大量的符号链接(这就是我如何到达这里)。

从技术上讲,没有内置的命令来编辑现有的符号链接。只需几个简短的命令就可以轻松实现。

下面是我为更新一个现有的符号链接而编写的一小段 Bash/zsh 函数:

# -----------------------------------------
# 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"
}

您可以通过以下两种方式之一修改所创建的软链接,如下所示

  1. 一种是您可以使用 rm 删除现有的软链接,然后使用 ln-s 命令再次创建新的软链接。
  2. 然而,这可以在一个步骤中完成,您可以使用“ ln-vfns Source _ path Destination _ path”命令将现有的软链接替换为更新后的路径。

列出目录中所有文件的初始化

$ ls -lrt
drwxrwxr-x. 3 root    root      110 Feb 27 18:58 test_script
$

使用 ln-s 命令为 test _ script 创建软链接测试。

$ ln -s test_script test
$ ls -lrt
drwxrwxr-x. 3 root    root      110 Feb 27 18:58 test_script
lrwxrwxrwx. 1 root    root       11 Feb 27 18:58 test -> test_script
$

使用新目录 test _ script/softlink 更新软链接测试,使用单个命令

$ ln -vfns test_script/softlink/ test
'test' -> 'test_script/softlink/'
$

列出新的软链接位置

$ ls -lrt
lrwxrwxrwx. 1 root    root       21 Feb 27 18:59 test -> test_script/softlink/
$

救... 救命

- v,——每个链接文件的详细打印名称

- f,-强制删除现有目标文件

如果 LINK _ NAME 是一个符号,则 no-dereference 将其视为普通文件

- s,-象征性建立符号链接而不是硬链接