k-R*_*ker 66 hard-link shell-script symlink files
我正在创建一个 shell 脚本,它将获取文件的文件名/路径并确定该文件是符号链接还是硬链接。
唯一的问题是,我不知道如何查看它们是否是硬链接。我创建了 2 个文件,一个是硬链接,一个是符号链接,用作测试文件。但是我如何确定一个文件是一个硬链接还是一个 shell 脚本中的符号?
另外,我如何找到符号链接的目标分区?因此,假设我有一个链接到不同分区的文件,我如何找到该原始文件的路径?
der*_*ert 50
Jim 的回答解释了如何测试符号链接:通过使用test's -Ltest.
但是,严格来说,测试“硬链接”并不是您想要的。硬链接之所以起作用,是因为 Unix 处理文件的方式:每个文件都由一个 inode 表示。然后单个 inode 具有零个或多个名称或目录条目,或者从技术上讲,硬链接(您称之为“文件”)。
值得庆幸的是,该stat命令(如果可用)可以告诉您一个 inode 有多少个名称。
所以你正在寻找这样的东西(这里假设 GNU 或 busybox 实现stat):
if [ "$(stat -c %h -- "$file")" -gt 1 ]; then
echo "File has more than one name."
fi
Run Code Online (Sandbox Code Playgroud)
该-c '%h'位告诉stat只输出到 inode 的硬链接数,即文件具有的名称数。-gt 1然后检查它是否大于 1。
请注意,符号链接与任何其他文件一样,也可以链接到多个目录,因此您可以将多个硬链接指向一个符号链接。
Sté*_*las 34
一个例子:
$ touch f1
$ ln f1 f2
$ ln f1 f3
$ ln -s f1 s1
$ ln -s f2 s2
$ ln -s ./././f3 s3
$ ln -s s3 s4
$ ln s4 s5
$ ls -li
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802345 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s1 -> f1
10802346 lrwxrwxrwx 1 stephane stephane 2 Nov 12 19:56 s2 -> f2
10802347 lrwxrwxrwx 1 stephane stephane 8 Nov 12 19:56 s3 -> ./././f3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s4 -> s3
10802384 lrwxrwxrwx 2 stephane stephane 2 Nov 12 19:56 s5 -> s3
Run Code Online (Sandbox Code Playgroud)
的f1,f2和f3目录条目是相同的文件(相同的inode:10802124,你会发现数量链接为3)。它们是指向同一个常规文件的硬链接。
s4并且s5也是同一个文件 (10802384)。它们属于symlink类型,而不是常规类型。他们指向一条路径,这里s3。因为s4和s5是同一目录的条目,所以相对路径s3指向同一个文件(inod 10802347 的文件)。
如果您执行ls -Ll,则要求在解析符号链接后获取文件信息:
$ ls -lLi
total 0
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s1
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s2
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s3
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s4
10802124 -rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 s5
Run Code Online (Sandbox Code Playgroud)
您会发现它们都解析为同一个文件 (10802124)。
您可以检查文件是否是带有[ -L file ]. 同样,您可以使用 测试文件是否为常规文件[ -f file ],但在这种情况下,在解析符号链接后进行检查。
硬链接不是一种文件,它们只是文件(任何类型)的不同名称。
jim*_*-cl 21
使用命令的-h和-L运算符test:
-h file
true if file is a symbolic link
-L file
true if file is a symbolic link
Run Code Online (Sandbox Code Playgroud)
http://www.mkssoftware.com/docs/man1/test.1.asp
根据这个 SO thread,它们具有相同的行为,但-L更受欢迎。
小智 6
你可以使用readlink FILE; echo $?. 当它是硬链接时返回 1,当它是符号链接时返回 0。
来自手册页:“当作为 readlink 调用时,只打印符号链接的目标。如果给定的参数不是符号链接,则 readlink 将不打印任何内容并退出并出现错误。”
这里有很多非常正确的答案,但我认为没有人真正解决最初的误解。最初的问题基本上是“当我制作符号链接时,之后很容易识别它。但我不知道如何识别硬链接。” 是的,答案基本上归结为“你不能”,并且或多或少地解释了原因,但似乎没有人承认,真的,这令人困惑和奇怪。
如果你正在阅读所有这些并且你已经弄清楚发生了什么,那么你很好;你不需要阅读我的一点点。如果您仍然感到困惑,请继续。
真正非常简短的答案是硬链接根本不是真正的链接,不像符号链接那样。它是目录结构中的一个新条目,指向与原始目录条目相同的字节串,一旦您创建了它,它就与第一个一样“真实”和合法。驱动器上的每个“普通”文件都至少有一个硬链接;没有它,你就不会在任何地方看到它目录,并且无法引用或使用它。因此,如果您有一个文件 Fred.txt,并且您将 Wilma.txt 和 Barney.txt 硬链接到它,则所有三个名称(和目录条目)都引用同一个文件,并且它们都同样有效。当您在文本编辑器中点击“保存”时,操作系统无法判断其中一个条目是创建的,而其他条目是使用“ln”命令创建的。
不过,操作系统确实必须跟踪有多少不同的条目指向同一个文件。如果您删除 Wilma.txt,您不会释放驱动器上的任何空间也就不足为奇了。但是,如果您删除 Fred.txt(“原始”文件),您仍然不会释放驱动器上的任何空间,因为驱动器上称为 Fred.txt 的数据仍然是 Barney.txt。只有当您删除所有目录条目时,操作系统才会取消分配数据本身占用的空间。
如果 Barney.txt 是一个符号链接,那么删除 Fred.txt将取消分配空间,而 Barney.txt 现在将是一个断开的链接。此外,如果您移动或重命名具有指向它的符号链接的文件,则会断开链接。但是您可以随意移动或重命名硬链接文件,而不会破坏指向该文件/数据的其他目录条目,因为它们都是引用驱动器上相同数据块的目录条目(通过使用该数据的 inode #)。
[这是两年后,这最后一点困惑了我一分钟,所以我想我会澄清。如果您输入“mv ./Wilma.txt ../elsewhere/Betty.txt”,您似乎在移动文件,但实际上并非如此。您真正要做的是从当前目录的目录列表中删除一个行项目,该项目表示“名称'Wilma.txt'与可以通过使用 inode ###### 找到的数据相关联#,”并在目录 ../elsewhere 的目录列表中添加一个新的行项目,表示“名称 'Betty.txt' 与可以通过 inode ####### 找到的数据相关联。这就是为什么您可以像 2 KB 文件一样快速“移动” 2 GB 的文件,只要您将它们移动到同一驱动器上的另一个位置即可。]
由于操作系统必须跟踪有多少不同的目录条目指向同一块数据,因此您可以判断某个特定文件是否已被硬链接,即使您无法确定您所使用的目录条目是否已被硬链接。 '正在看是'原版' 一个与否。一种方法是“ls”命令,特别是“ls -l”(破折号后的小写L)
借用之前的例子......
-rw-r--r-- 3 stephane stephane 0 Nov 12 19:55 f1
Run Code Online (Sandbox Code Playgroud)
第一个字母是破折号,所以它不是目录或其他异国情调的东西,它是一个“常规”普通文件。但如果它真的很普通,那么 rwx-ish 部分之后的数字将是“1”,如“有一个目录条目指向这个数据块”。但它是硬链接演示的一部分,所以它改为“3”。
请注意,这可能会导致奇怪和神秘的行为(如果您还没有考虑硬链接的话)。如果您在文本编辑器中打开 Fred.txt 并进行一些更改,您会在 Wilma.txt 和 Barney.txt 中看到相同的更改吗?也许。大概。如果您的文本编辑器通过打开原始文件并将更改写入其中来保存更改,那么是的,所有三个名称仍将指向相同(新更改的)文本。但是,如果您的文本编辑器创建了一个新文件 (Fred-new-temp.txt),将更改后的版本写入该文件,然后删除 Fred.txt,然后将 Fred-new-temp.txt 重命名为 Fred.txt,Wilma 和 Barney 就会仍然指向原始版本,而不是新的更改版本。如果您不了解硬链接,这可能会让您有点抓狂。:) [好吧,我个人实际上并不知道任何可以执行新文件/重命名操作的文本编辑器,但我知道很多其他程序正是这样做的,所以请保持警惕。]
最后一点:“fsck”(文件系统检查)检查的其中一项内容是驱动器上是否存在任何目录条目不再引用的数据块。有时会出错,指向 inode 的唯一目录条目会被删除,但驱动器空间本身并未标记为“可用”。所以 fsck 的工作之一是将所有分配的空间与所有目录条目匹配,以确保没有任何未引用的文件。如果找到了一些,它会创建新的目录条目并将它们放在“lost+found”中。