断开文件夹中的所有硬链接


10

我有一个文件夹,其中包含一定数量的具有硬链接的文件(在同一文件夹或其他位置),并且我想取消对这些文件的硬链接,以使它们变得独立,并且对其内容的更改不会影响任何文件。其他文件(其链接计数变为1)。

下面,我给出一个解决方案,该解决方案基本上将每个硬链接复制到另一个位置,然后将其移回原位。

但是,此方法似乎很粗糙且容易出错,因此我想知道是否有一些命令可以为我取消硬链接。

粗略的回答:

查找具有硬链接的文件(编辑:要查找具有硬链接的套接字等,请使用find -not -type d -links +1):

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

取消硬链接的粗略方法(将文件复制到另一个位置,然后将其移回): 编辑: 正如Celada所说,最好在下面执行cp -p以避免丢失时间戳和权限。 编辑: 创建一个临时目录并将其复制到该目录下的文件中,而不是覆盖临时文件,尽管该mv命令仍然存在风险(感谢@Tobu),但它将使覆盖某些数据的风险降到最低。 编辑: 尝试在同一文件系统(@MikkoRantalainen)中创建临时目录。

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

因此,要取消硬链接所有硬链接(编辑:更改-type f-not -type d,请参见上文):

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh

我不会认为这是“粗鲁的”。提高速度的唯一方法可能是对sendfile()系统调用进行一些技巧,并取消链接开源文件并就地重写目标。坦率地说,它不值得付出努力。
马修·伊夫

所谓“粗略”,是指,例如,当我使用cp -i开关运行此命令时,即使tmpfile应该提供唯一的文件名,它也会向我吐出几条消息询问是否应覆盖./fileXXXXXX$temp文件),因此必须处于某种竞争状况或其他任何情况,并有失去一些数据的风险。
苏珊·杜彭(SuzanneDupéron)

1
该文件存在是正常的,您只是使用tempfile创建了它(nb:不推荐使用mktemp,但这不是造成问题的原因)。
东武

1
unhardlink.sh应该在包含需要取消链接的文件的同一目录内创建一个临时目录。否则,您的递归调用可能会在另一个文件系统内递归,并且由于临时目录位于当前工作目录中,因此最终您会在文件系统边界上移动内容。我想您可以将其"$(dirname "$i")/hardlink-XXXXXX"作为参数传递给mktemp。
Mikko Rantalainen'1

1
@MikkoRantalainen非常感谢,已更新!请注意,如果文件系统是某种unionfs或fuse文件系统,则它实际上可能分派path/to/hardlink-XXX到与之外的其他物理存储介质上path/to/original-file,但是对此并没有太多的事情要做。
SuzanneDupéron,

Answers:


9

脚本中还有改进的余地,例如-p,在cp命令中添加一个选项,以便在unhardlink操作中保留权限和时间戳,还可以添加一些错误处理,以便在发生错误时删除临时文件,但解决方案的基本思想是唯一可行的解​​决方案。要取消链接文件,您必须先将其复制,然后再将副本移回原始名称。没有“较简单的”解决方案,并且在另一个进程同时访问文件的情况下,此解决方案具有竞争条件。


确实,在复制内容时,我总是使用cp -a来保留所有内容,递归并将符号链接复制为符号链接。不知道为什么我这次忘记了它,但是在看到您的回答后,我知道我已经弄糟了所有时间戳,不得不(而不是痛苦地)从备份中恢复它们。
苏珊·杜彭(SuzanneDupéron)

5

如果您想消耗磁盘空间,并且拥有相对较新的版本tar(例如,Ubuntu 10.04和CentOS 6上的版本),则可以使用该--hard-dereference选项。

就像是:

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(我跑过的地方ln foo/[12] bar

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

从手册页:

   --hard-dereference
          follow hard links; archive and dump the files they refer to

我怀疑几乎没有焦油可以做。好的修复。
2012年

我忘了提到我没有足够的磁盘空间来复制所有内容。基本上,cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder如果我没有记错的话,您的方法与相同。我想您的方法会更有效,因为tar会减少磁盘寻道,从而减少抖动。使用rsync可以达到相同的效果,甚至比cp方法还低:)。
苏珊·杜彭(SuzanneDupéron)

1
为了避免使用过多的磁盘,可能会运行类似的命令,tar cvf - --hard-dereference . | tar xf -但是可能存在竞争状况,这会导致事情爆炸。我还没有尝试过,目前我不愿意这样做。
cjc 2012年
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.