你能改变一个符号链接创建后指向的内容吗?

时间:2009-09-23 14:58:13

标签: unix symlink

是否有任何操作系统提供一种机制(系统调用 - 而不是命令行程序)来更改符号链接(符号链接)引用的路径名 - 除了取消旧链接和创建新链接之外的其他路径名?

POSIX标准没有。 Solaris 10没有。 MacOS X 10.5(Leopard)没有。 (我很可能确定AIX和HP-UX都没有。从这个Linux system calls列表来看,Linux也没有这样的系统调用。)

有什么用吗?

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


由于证明消极是很难的,让我们重新组织这个问题。

如果您知道某些(类Unix)操作系统尚未列出系统调用,无需删除旧符号链接并创建新符号链接来重写符号链接的值(readlink()返回的字符串) ,请在答案中添加它 - 或者它们。

6 个答案:

答案 0 :(得分:153)

是的,你可以!

$ ln -sfn source_file_or_directory_name softlink_name

答案 1 :(得分:100)

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选项会使lnunlink()之前执行系统调用symlink() }}。下面,我的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

所以我猜最后的答案是“不”。

编辑:以下内容从Arto Bendiken's answer复制到unix.stackexchange.com,大约2016年。

这个可以确实以rename(2)原子方式完成,首先在临时名称下创建新的符号链接,然后一次性干净地覆盖旧的符号链接。正如man page所述:

  

如果 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

编者注:这是Capistrano多年来一直这样做的,从那时起〜2.15。请参阅this pull request

答案 2 :(得分:12)

没有必要明确取消链接旧的符号链接。你可以这样做:

ln -s newtarget temp
mv temp mylink

(或使用等效的符号链接并重命名调用)。这比显式取消链接更好,因为重命名是原子的,因此可以确保链接始终指向旧目标或新目标。但是,这不会重用原始的inode。

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

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

  

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

     

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

     

在Linux上,符号链接的权限不会在任何操作中使用;   权限始终为0777(所有用户的读取,写入和执行)   类别),并且不能改变。

答案 3 :(得分:2)

只是警告上面的正确答案:

如果混淆源和目标,使用-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

至少保留我的文件。

答案 4 :(得分:1)

不会取消链接并创建新版本最终会做同样的事情吗?

答案 5 :(得分:0)

以防它有所帮助:有一种方法可以使用午夜指挥官(mc)编辑符号链接。 菜单命令是(我的mc界面上的法语):

Fichier / Éditer le lien symbolique

可以翻译为:

File / Edit symbolic link

快捷方式是C-x C-s

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

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