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

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

我有一个文件夹,其中包含一定数量的具有硬链接的文件(在同一个文件夹或其他地方),我想取消这些文件的硬链接,以便它们变得独立,并且对其内容的更改不会影响任何其他文件(它们的链接数变为 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

答案1

您的脚本还有改进的空间,例如,在命令-p中添加一个选项cp,以便在取消硬链接操作过程中保留权限和时间戳,并且可以添加一些错误处理,以便在出现错误时删除临时文件,但您的解决方案的基本思想是唯一可行的。要取消硬链接文件,您必须复制它,然后将副本移回原始名称。没有“不那么粗糙”的解决方案,并且如果另一个进程同时访问该文件,此解决方案就会出现竞争条件。

答案2

如果您想要释放磁盘空间,并且您有一个相对较新的版本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

相关内容