多数の壊れたシンボリックリンクを「再リンク」するにはどうすればよいですか?


54

下にあるファイルへのシンボリックリンクの束があるディレクトリツリーがあります/home...しかし、私はすべてのシンボリックリンクに移動/home/mnt/home、「再リンク」する方法が必要です。そのような機能は存在しますか、それを行うためにスクリプトを記述する必要がありますか?

例として、次のようなものがあります。

[root@trees ~]# ls -l /mnt/home/someone/something
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/e

/mnt/home/someone/something/subdir:
total 4264
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 a -> /home/someone/someotherthing/subdir/a
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 b -> /home/someone/someotherthing/subdir/b
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 c -> /home/someone/someotherthing/subdir/c
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 d -> /home/someone/someotherthing/subdir/d
lrwxrwxrwx 1 jnet www-data      55 2011-08-07 13:50 e -> /home/someone/someotherthing/subdir/e

私はすべてのシンボリックリンクを見つけて同じ場所に再リンクするが、/mnt/home代わりに下にあるコマンドが必要です/home

そのようなコマンドは存在しますか?

回答:


55

シンボリックリンクを再ターゲットするコマンドはありません。できることは、それを削除して別のリンクを作成することだけです。あなたはGNUユーティリティを持っていると仮定すると(例えば、非組込みLinuxやCygwinの下)は、使用することができます-lnameが、主にfind彼らのターゲットにシンボリックリンクを一致させるために、およびreadlinkリンクの内容を読み取るために。未テスト:

find /mnt/home/someone/something -lname '/home/someone/*' \
     -exec sh -c 'ln -snf "/mnt$(readlink "$0")" "$0"' {} \;

これらのシンボリックリンクを相対的にする方が良いでしょう。symlinks多くのLinuxディストリビューションに存在する、便利な小さなユーティリティ(元々はMark Lordsにより、現在J. Brandt Buckleyにより管理されています)があります。移動する前、または上記のように有効なリンクを復元した後symlinks -c /mnt/home/someone/something、ファイルシステムの境界を超えない限り、指定したディレクトリの下のすべての絶対シンボリックリンクを相対シンボリックリンクに変換するために実行します。


オフェンスはありませんが、これは素晴らしいワンライナーですが、Bashの文字列置換はおそらくパスの変更に関して何らかの魔法を行うことができ、より簡単になるでしょう。
0xC0000022L

@STATUS_ACCESS_DENIEDどうして?唯一の文字列操作は/mnt、パスの先頭に追加することです。連結より複雑な文字列操作は必要ありません。
ジル「悪さSO-ストップ」

@Gilles:申し訳ありませんが、相対パスでの発言についてもっと考えていました。あなたの例の正確な「翻訳」については、もちろん正しいです。
-0xC0000022L

13

私はこれが著者が要求しているものとまったく同じではないことを知っていますが、彼らはすでに彼らの答えを持っているようです。

シンボリックリンクのターゲットの一部を交換することで修正できる多数の壊れたシンボリックリンクを作成するなど、より柔軟なソリューションが必要な場合は、以下が役立ちます。

例えば。ユーザー名の変更後、移動が既に行われた後、多くのリンクのターゲットで古いユーザー名を新しいユーザー名に置き換えるため。次に示すreplace-simlinksというスクリプトを作成します。

#!/bin/bash
link=$1
# grab the target of the old link
target=$(readlink -- "$1")

# replace the first occurrence of oldusername with newusername in the target string
target=${target/oldusername/newusername}

# Test the link creation
echo ln -s -- "$target" "$link"

# If the above echo shows the correct commands are being issued, then uncomment the following lines and run the command again
#rm $link
#ln -s "$target" "$link"

次のコマンドで呼び出します:

find /home/newusername/ -lname '/home/oldusername/*' -exec ~/bin/replace-simlinks {} \;

これが誰かを助けることを願って

編集:このスクリプトのキックスタートと、リンクを相対リンクにするためのsymlinksスクリプトの使用に関するヒントについて、Gillesに感謝します。


1
このソリューションは文字列置換を使用しているため、パスの途中にあるフォルダーの名前を変更する必要がある場合に役立ちます。また、必要に応じて、より複雑な変換を実行するために、ソリューションを非常に簡単に変更できます。
Gallaecio

文字列置換の引数を引用することをお勧めします。これは、たとえばOPの質問のパスなど、スラッシュを使用するために行う必要があるためです。target=${target/"/home"/"/mnt/home"}でもとても助かります。ありがとう。
ウォルターニッセン

3

/homeへのシンボリックリンクとして作成する/mnt/homeと、既存のすべてのシンボリックリンクが再び有効になります。


2
バインド・マウントは、多くの場合、...プログラムは、シンボリックリンクを認識しているが、実際に応じて、異なる動作シナリオにおけるシンボリックリンクより壊れにくくなる傾向がある
0xC0000022L
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.