命令行基础知识:符号链接

介绍

Symbolic links 允许您将文件和目录链接到其他文件和目录. 它们以许多名称进行链接,包括simlinks,shell links,soft links,shortcuts和代码。 从用户的角度来看,符号链接与正常文件和目录非常相似。

本指南概述了什么是符号链接,以及如何使用ln命令从Linux命令行创建它们。

前提条件

要跟随这个指南,你需要访问运行基于Linux的操作系统的计算机. 它可以是一个虚拟的私人服务器,你已经连接到SSH或你的本地机器. 请注意,本教程是通过使用运行Ubuntu 20.04的Linux服务器验证的,但所示的例子应该在运行任何Linux发行版的计算机上工作。

如果您打算使用远程服务器来遵循本指南,我们建议您先完成我们的 初始服务器设置指南

设置示例目录和文件

创建符号链接所需的系统呼叫通常在 Unix 类型和 POSIX 兼容的操作系统上可用,我们将用来创建链接的命令是ln

您可以使用系统上的现有文件来练习创建象征链接,但本节提供了一些命令,将设置一个练习环境,您可以跟随本指南的示例。

首先,在/tmp/目录中创建一对目录,/tmp/是一个临时目录,这意味着在服务器下次启动时将删除其中的任何文件和目录,这将对本指南的目的有用,因为您可以创建尽可能多的目录,文件和链接,而无需担心它们在以后会堵塞您的系统。

以下mkdir命令同时创建三个目录,在/tmp/目录中创建一个名为symlinks/的目录,并在symlinks/中创建两个目录(一个名为one/和另一个名为two/):

1mkdir -p /tmp/symlinks/{one,two}

导航到新的symlinks/目录:

1cd /tmp/symlinks

从那里,创建一对样本文件,一个为symlinks/中的两个子目录。下列命令在one/子目录中创建一个名为one.txt的文件,其唯一内容是单行读one:

1echo "one" > ./one/one.txt

类似地,这个命令在two/子目录中创建了一个名为two.txt的文件,其唯一内容是单行阅读two:

1echo "two" > ./two/two.txt

如果在这一点上运行,以显示整个/tmp/symlinks目录和任何嵌入的子目录的内容,其输出将是这样的:

1tree
1[secondary_label Output]
2.
3├── one
4│   └── one.txt
5└── two
6    └── two.txt
7
82 directories, 2 files

<$>[注] :如果「tree」默认不安装在您的计算机上,您可以使用您的系统的包管理器来安装它。

1sudo apt install tree

美元

有了这些样本文件,你准备好练习构建象征性链接。

理解硬左翼

默认情况下,ln命令将创建 _hard links,而不是象征性或软性链接。

假设你有一个文本文件. 如果你把一个符号链接到该文件,链接只是指向原始文件. 如果你删除原始文件,链接将被打破,因为它不再有任何东西要指向。

相反,硬链接是原始文件的镜像副本,内容完全相同。像符号链接一样,如果您编辑原始文件的内容,这些变化将反映在硬链接中。

硬链接在世界中服务于其目的,但在某些情况下应该完全避免,例如,当链接到git存储库时,您应该避免使用硬链接,因为它们可能会引起混淆。

要确保您正在创建符号链接,您可以将-s--symbolic选项传递给ln命令。

<$>[注] :由于象征链接通常比硬链接更频繁使用,有些人可能认为对lnln -s的代码有益:

1alias ln="ln -s"

这可能只节省了一些键,但如果你发现自己做了很多符号链接,这可能会显著增加

使用符号链接

如前所述,象征链接本质上就像创建一个包含目标文件名和路径的文件一样,因为象征链接只是对原始文件的参考,所以对原始文件所做的任何更改都将在象征链接中立即可用。

象征链接的一个潜在用途是创建用户主目录中的本地目录,指向文件同步到外部应用程序,如 Dropbox。

使用第一个部分的示例文件和目录,继续创建一个名为的象征链接,指向您之前创建的目录:

1ln -s one three

现在您应该有 3 个目录,其中一个目录指向另一个目录. 要获得当前目录结构的更详细的概述,您可以使用ls命令来打印当前工作目录的内容:

1ls
1[secondary_label Output]
2one three two

现在在symlinks/目录中有三个目录. 根据您的系统,这可能意味着实际上是一个象征性的链接. 这有时是通过以不同的颜色渲染链接的名称或附加一个@符号来完成的。

要了解更多细节,您可以将-l参数传递给ls,以确定象征链接实际指向何处:

1ls -l
1[secondary_label Output]
2total 8
3drwxrwxr-x 2 sammy sammy 4096 Oct 30 19:51 one
4lrwxrwxrwx 1 sammy sammy 3 Oct 30 19:55 three -> one
5drwxrwxr-x 2 sammy sammy 4096 Oct 30 19:51 two

请注意,链接按预期指向目录,也以l开头,表示是链接,另外两个链接则以d开头,意思是它们是常规目录。

符号链接也可以包含符号链接,例如,将中的one.txt文件链接到两个目录:

1ln -s three/one.txt two/one.txt

你现在应该有一个名为one.txt的文件在两个目录中,你可以用以下ls命令检查:

1ls -l two/
1[secondary_label Output]
2total 4
3lrwxrwxrwx 1 sammy sammy 13 Oct 30 19:58 one.txt -> three/one.txt
4-rw-rw-r-- 1 sammy sammy 4 Oct 30 19:51 two.txt

根据您的终端配置,链接(在本示例输出中突出)可能以红色文本进行渲染,表示链接被打破.虽然链接被创建,但本示例指定路径的方式是相对的. 链接被打破,因为两个目录不包含三个目录,其中包含one.txt文件。

幸运的是,您可以通过告诉ln创建与链接位置相关的象征链接,使用-r--相对参数来修复这种情况。

然而,即使使用-r旗,您也无法修复破碎的象征链接,原因是象征链接已经存在,您也无法在不包括-f--force参数的情况下重写它:

1ln -srf three/one.txt two/one.txt

有了这个,你现在有‘two/one.txt’ 链接到‘three/one.txt’ 这是一个链接到‘one/one.txt’。

像這樣的符號鏈接可以很快變得困惑,但許多應用程式都配備了這樣的連結結構,以便讓這些連結結構更容易理解。

1tree
 1[secondary_label Output]
 2.
 3├── one
 4│   └── one.txt
 5├── three -> one
 6└── two
 7    ├── one.txt -> ../one/one.txt
 8    └── two.txt
 9
103 directories, 3 files

现在,事情已经很好地连接在一起,您可以通过更改这些样本文件的内容来开始探索象征链接如何与文件工作。

要了解您的文件包含了什么,请运行以下cat命令,在本指南中创建的三个目录中的每个中打印one.txt文件的内容:

1cat {one,two,three}/one.txt
1[secondary_label Output]
2one
3one
4one

接下来,从one/目录中更新原始one.txt文件的内容:

1echo "1. One" > one/one.txt

然后再检查每个文件的内容:

1cat {one,two,three}/one.txt
1[secondary_label Output]
21. One
31. One
41. One

正如此输出所示,您对原始文件所做的任何更改都将反映在其任何符号链接中。

现在尝试反过来,运行以下命令来更改一个符号链接的内容. 此示例更改了三/目录中的one.txt文件的内容:

1echo "One and done" > three/one.txt

然后再检查每个文件的内容:

1cat {one,two,three}/one.txt
1[secondary_label Output]
2One and done
3One and done
4One and done

由于您更改的符号链接只是指向另一个文件的指针,所以您对该链接的任何更改都会立即反映在原始文件中以及其它任何符号链接中。

结论

符号链接可以非常有用,但它们确实有某些局限性。请记住,如果您要移动或删除原始文件或目录,所有现有的符号链接将被打破。

Published At
Categories with 技术
comments powered by Disqus