ディレクトリを指すシンボリックリンクを作成するために使用できるべき等べきコマンドは何ですか?


16

ディレクトリへのシンボリックリンクを作成するシェルスクリプトにコマンドを配置したいのですが、このスクリプトは何度も実行される可能性があるため、以降の呼び出しでは、コマンドは何も変更しません。

ディレクトリ構造は次のとおりです。

% tree /tmp/test_symlink 
/tmp/test_symlink
├── foo
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

foo/ディレクトリを指すスニペットと呼ばれるシンボリックリンクを作成したいと思います/tmp/test_symlink/repo/resources/snippets
だから私は実行します:

% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets' -> '/tmp/test_symlink/repo/resources/snippets'

望ましい結果が得られます。

% tree /tmp/test_symlink                                                          
/tmp/test_symlink
├── foo
   └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

5つのディレクトリ、5つのファイル

ただし、コマンドを再度実行すると、

% ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/snippets
'/tmp/test_symlink/foo/snippets/snippets' -> '/tmp/test_symlink/repo/resources/snippets'

ディレクトリへのシンボリックリンクを作成します。シンボリックリンクが存在する場所では、実際のディレクトリ内にシンボリックリンクを配置します

% tree /tmp/test_symlink                                                          
/tmp/test_symlink
├── foo
   └── snippets -> /tmp/test_symlink/repo/resources/snippets
└── repo
    └── resources
        └── snippets
            ├── php.snippets
            ├── sh.snippets
            ├── snippets -> /tmp/test_symlink/repo/resources/snippets
            ├── snippets.snippets
            ├── sql.snippets
            └── vim.snippets

なぜこれが起こっているのですか、その後の呼び出しでこの奇妙な効果が発生しないようにコマンドを変更するにはどうすればよいですか?

回答:


16

-Tこれにはオプションを使用する必要があります。lnリンク名を常にディレクトリとしてではなく、目的のリンク名として常に扱うように指示します。

このオプションを使用しない場合ln、ディレクトリとして存在するリンク名を指定すると、そのディレクトリ内にターゲットへの新しいリンクが作成されます。

これ-TはGNU主義であることに注意してください(少なくとも、それはPOSIXにはありません)が、すでに使用し-vているのはGNU主義でもあるので、問題ではないと思います。

または、親ディレクトリをリンク名として指定するだけで、そこにリンクが常に(再)作成されます:

ln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/

これは、シンボリックリンクがターゲットと同じ名前を持っているため機能します。


おかげで、はい、gnuオプションは必ずしも移植性があるわけではありませんが、移植性が要求されない場合、本当に便利です。あなたの答えは私のために働く。マニュアルページから-n, --no-dereference treat LINK_NAME as a normal file if it is a symbolic link to a directory-T, --no-target-directory treat LINK_NAME as a normal file always常にシンボリックリンクをファイルとして扱う方が良いと思いますか?これらの「特別な」オプションの使用を制限する方が良いと思いましたか?
-the_velour_fog

それらが利用可能であることを知っていれば、GNU固有のオプション(IMO)を避ける理由はありません。あなたはdem等コマンドを要求しました、それ-Tはhow ln等を作る方法です。必要に応じて同じ結果を得る他の方法があります。たとえば、リンクを削除して再作成する場合、またはfoo既に存在することがわかっている場合ですln -sfv /tmp/test_symlink/repo/resources/snippets /tmp/test_symlink/foo/(実際、それは完全に良い答えかもしれませんが、更新します)。
スティーブンキット

1
クール、はい私は、以前使用していたifシンボリックリンクの存在を検出し、シンボリックリンクが存在する場合、コマンドをスキップする文を、しかし、スクリプトは使用しないように、私は、何かの冪等はなく、単純なために起こっていた読み取りに雑然とし、ハードになってしまうmkdir -p何のテストを、ロジックはなく、1つのライナーのみで良い:)
the_velour_fog

@Stephen Kitt:-Tの使用について言及しましたが、回答のコードスニペットでそれを見つけることができませんでした。私は何かを誤解したり見落としたりしていますか?
-Guizmoo03

@ Guizmoo03は、おそらくスニペットを紹介する「代替」を見逃したでしょう。最初の3つのパラグラフは説明-Tしますが、私の答えの終わりは使用しない別のソリューションを提示します-T
スティーブンキット

-1

私はここで何が起こっているかを伝えることができるベストは上が第二渡すことであるlnようなコマンド振る舞いをcpmv、それは、<送信先>の「ディレクトリ」を見れば、<送信先>がない場合、それは他に、その中にファイルを置くことです、存在する場合、<destination>になります。(これは、「スラッシュドット」トリックが回避するものです。つまり、<destination>が存在し、ディレクトリであることを確認します)。
しかし、私は間違っている可能性があります。

どちらの場合でも、これはうまくいくようです

ln -sfv --no-dereference /tmp/test_symlink/repo/resources/snippets/ foo/snippets
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.