子目录中的Symlink别名文件不更改当前目录


11

在不移动子目录的情况下,将一个文件符号链接到子目录中的新文件似乎很简单。但是有关语法的某些问题令人困惑,并且与我的期望背道而驰。这是一个测试案例:

mkdir temp
cd temp
mkdir deploy
echo "Contents of the build file!" > deploy/resources.build.php
ln -s deploy/resources.build.php deploy/resources.php
cat deploy/resources.php #bad symlink

这只会创建一个损坏的符号链接!我正在构建环境安装脚本中运行此脚本,因此,我尽可能避免更改当前工作目录。

ln -s deploy/resources.build.php resources.php
cat deploy/resources.php

也不起作用,因为它在temp目录而不是deploy子目录中创建符号链接。

cd deploy
ln -s resources.build.php resources.php
cd ..

这行得通,但我更希望知道如何在不更改目录的情况下进行操作。

使用完整路径,例如:

/home/whatever/src/project/temp/stuff/temp/deploy/resources.build.php

是可行的,但不可行且有些不切实际,尤其是在构建环境中,其中所有项目内容在构建之间可能会有所不同,等等。

如何在子目录中的两个文件之间创建符号链接,而又不移入该子目录,也不能为该文件赋予新的别名?

Answers:


10

但是有关语法的某些问题令人困惑,并且与我的期望背道而驰。

ln以的形式使用的参数为:

ln [OPTION] ... [-T] TARGET LINK_NAME(第一种形式)

令人困惑,不直观的事情是,当您创建符号链接时,预期目标参数ln不是文件的路径,而是要创建的符号链接的内容。如果您想一会儿,很明显它一定是那样的。考虑:

$ echo foo >foo
$ ln -s foo bar1
$ ln -s $PWD/foo bar2
$ cat bar1
foo
$ cat bar2
foo
$ ls -l bar1 bar2
lrwxrwxrwx 1 matt matt  3 Dec 29 16:29 bar1 -> foo
lrwxrwxrwx 1 matt matt 29 Dec 29 16:29 bar2 -> /home/matt/testdir/foo

在该示例中,我创建了两个指向相同文件的符号链接,分别名为“ bar1”和“ bar2”。 ls显示符号链接本身具有不同的内容-一个包含绝对路径,一个包含相对路径。因此,即使将目录移动到另一个目录,它也将继续工作,而另一个目录则不会:

$ mv bar2 /tmp
$ cat /tmp/bar2
foo
$ mv bar1 /tmp
$ cat /tmp/bar1
cat: /tmp/bar1: No such file or directory

因此,考虑到我们必须既可以建立相对符号链接,也可以建立绝对符号链接,甚至可以创建断开的符号链接,如果以后创建目标文件,这些符号链接也将不中断,则目标参数必须解释为自由格式的文本,而不是已有文件的路径。

如果要创建一个名为deploy / resources.php的文件,该文件链接到deploy / resources.build.php,则需要确定是否要创建一个绝对的符号链接(可以抵抗移动的符号链接,但如果目标已移动)或相对符号链接(只要符号链接和目标一起移动并保持相同的相对路径,该符号链接将继续工作)。

要创建绝对符号链接,可以执行以下操作:

$ ln -s $PWD/deploy/resources.build.php deploy/resources.php

要创建相对路径,首先要弄清楚从源到目标的相对路径。在这种情况下,由于源和目标相对于彼此位于同一目录中,因此您可以执行以下操作:

$ ln -s resources.build.php deploy/resources.php

如果它们不在同一目录中,则需要执行以下操作:

$ ln -s ../foo/f bar/b

在这种情况下,即使foobar都位于当前目录中,您也需要../ln 目标中包括a ,因为它描述了如何f从包含的目录中查找b

这是一个很长的解释,但是希望它可以帮助您ln更好地理解语法。


3

您可以在子shell中创建链接,如下所示:

  (cd deploy && ln -s resources.build.php resources.php && cat resources.php)

当子shell结束执行时,您将发现自己仍在正确的目录中。

或者,您可以尝试

 ln -s resources.build.php deploy/resources.php

这也起作用,忽略了在CL中包括文件resources.build.php不在发出命令的目录中,而是实际上在./deploy内部的事实。


先生,这是黑魔法!
Kzqai 2014年

1

这让我感到困惑,直到我意识到符号链接基本上是一个配置文件。即我如何将路径数据写入一个简单的文本文件:

ln -s [target] [link name]

变成:

echo [target] > [link name]

我(可能还有OP)所犯的错误是认为ln需要了解其目标文件。ln不在乎。它只是将一些路径信息写入文件中。这是一个非常合理的ln命令:

ln -s /path/doesnt/exist/file.err
ll
file.err -> /path/doesnt/exist/file.err

因此:

ln -s deploy/resources.build.php deploy/resources.php

生成一个resources.php./deploy文件夹中称为的simlink文件,该文件引用该文件resources.build.php夹中的文件./deploy/deploy/

那不是您想要的,并且给出了错误的(断开)链接。链接没有任何问题,如果将文件放在此处,则链接有效。但是,(正如其他人所指出的)我和OP想要的是:

ln -s resources.build.php deploy/resources.php
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.