web-dev-qa-db-ja.com

ハードリンクをシンボリックリンクに変換する

_ln -f_( example )を使用して、シンボリックリンクをハードリンクに変換するのは簡単です。

両方のファイルを知っていてどちらかを自分で定義する場合は、ハードリンク(ファイル名linkおよびoriginal)を_link->original_へのシンボリックリンクに戻すのも簡単です。 「元のファイル」。簡単なスクリプト_convert-known-hardlink-to-symlink_を簡単に作成して、次のような結果にすることができます。

_convert-known-hardlink-to-symlink link original
$ ls -li
3802465 lrwxrwxrwx 1 14 Dec  6 09:52 link -> original
3802269 -rw-rw-r-- 1  0 Dec  6 09:52 original
_

ただし、作業ディレクトリ(デフォルトは_./_)と検索ディレクトリを定義できるスクリプトがあると非常に便利です。同じiノードを持つファイルを検索(デフォルトは_/_)し、それらすべてのハードリンクをシンボリックリンクに変換する場所。

その結果、定義された作業ディレクトリで、ハードリンクであるすべてのファイルが、代わりに同じiノードを持つ最初に見つかったファイルへのシンボリックリンクに置き換えられます。


開始はfind . -type f -links +1 -printf "%i: %p (%n)\n"になります

4
rubo77

これを行うスクリプトを作成しました。スクリプトは、ソースディレクトリ(最初の引数)で見つかった、作業ディレクトリ(オプションの2番目の引数)と同じすべてのハードリンクをシンボリックリンクに変換します。

https://Gist.github.com/rubo77/7a9a83695a28412abbcd

ドライランのオプション-nがあり、何も実行しませんが、何が実行されるかを示します。

主要部分:

$WORKING_DIR=./
#relative source directory from working directory:
$SOURCE_DIR=../otherdir/with/hard-links/with-the-same-inodes

# find all files in WORKING_DIR
cd "$WORKING_DIR"
find "." -type f -links +1 -printf "%i %p\n" | \
  while read working_inode working_on
do
    find "$SOURCE_DIR" -type f -links +1 -printf "%i %p\n" | sort -nk1 | \
      while read inode file
    do
        if [[ $inode == $working_inode ]]; then
            ln -vsf "$file" "$working_on"
        fi
    done
done

-links + 1->複数のリンクを持つすべてのファイルを検索します。ハードリンクされたファイルのリンク数は少なくとも2つです。

4
rubo77

少なくともGNU findでは、数値(-inode)またはリンク(-samefile)を指定して、iノードで検索することもできます。

したがって、次を使用できます。

find "$WORKING_DIR" -type f -links +1 | while read file
do
  find "$SOURCE_DIR" -samefile "$file" -exec ln -vsf '{}' "$file" \;
done

必ず別々のディレクトリを使用する必要があります。一方、ファイルをそれ自体にリンクしようとすると、lnは文句を言います。

また、$SOURCE_DIRの絶対パスを指定するか、lnとともに-rオプションを使用して相対リンクを作成する必要があります。そうしないと、リンクが壊れることがあります。

1
digastricus