web-dev-qa-db-ja.com

シンボリックリンクを編集するにはどうすればよいですか?

シンボリックリンクについての私の基本的な理解は、特別なファイル、別のファイルへの文字列パスを含むファイルとしてです。カーネルのVFSはその多くを抽象化していますが、シンボリックリンクを編集できないように見える理由はありますか?

つまり、シンボリックリンクを編集できますか?そうでない場合、なぜそうではないのですか?


置換シンボリックリンクにはさまざまな方法があることを理解しています(現在、2つの選択肢が回答セクションにあります)。 。なぜあなたは彼らが指す場所を変えることができないのですか?

66
Oli

-fがサイレント置換を行うだけの場合、 mv -Tでアトミック置換を実行できます(-Tを指定すると、/ loc .../linkがディレクトリであっても機能します) =:

ln -s /location/to/link linkname
# ... 
ln -s /location/to/link2 newlink
mv -T newlink linkname

linknameはプロセス全体を通じてアクセスできます。

37
Oli

編集する場合は、それが指すファイルを変更することを意味し、そうすることができます。

_$ ln -s .bashrc test
$ ls -al test
lrwxrwxrwx 1 Pascal pascal 7 2009-09-23 17:12 test -> .bashrc
$ ln -s .profile test
ln: creating symbolic link `test': File exists
$ ln -s -f .profile test
$ ls -al test
lrwxrwxrwx 1 Pascal pascal 8 2009-09-23 17:12 test -> .profile
_

_-f_パラメータ(_--force_)をlnに渡すと、unlink()システムコールがsymlink()の直前に呼び出されます。

以下から取得 スタックオーバーフローの回答

23
NlightNFotis

シンボリックリンクはアトミックに変更する必要があります。あなたがそれらを書いている途中である場合、それらは動作しません。シンボリックリンクの内容は非常に小さい(Linuxでは最大4095文字:ファイルへのパスの最大長)ので、カーネルレベルでシンボリックリンクの一部を編集しても意味がありません。したがって、カーネルはシンボリックリンクを編集するためのインターフェイスを提供せず、新しい変数を作成するためのインターフェイス、symlinkシステムコール(およびファイルを削除するための汎用インターフェイスunlink)のみを提供します。

symlinkシステムコールは、新しいシンボリックリンクを作成するだけで、既存のファイルは削除しません。これは厄介ですが、open(新しいファイルを作成するか、既存のファイルを切り捨てることはできますが、既存のファイルを新しく作成されたファイルで置き換えることはできません)やmkdirなどのファイルを作成する他のシステムコールと一貫しています。

シェルでは あなたが発見した のように、シンボリックリンクをlnコマンド(ln -sfは、前のファイルのリンクを解除してからシンボリックリンクを作成します)。最初に一時的な名前でシンボリックリンクを作成してから、所定の場所に移動します。

tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"

技術的には、既存のシンボリックリンクを編集するための組み込みコマンドはありません。これは、いくつかの短いコマンドで簡単に実現できます。

ここに少しありますbash/zsh function既存のシンボリックリンクを更新するために書きました:

# -----------------------------------------
# Edit an existing symbolic link
#
# @1 = Name of symbolic link to edit
# @2 = Full destination path to update existing symlink with 
# -----------------------------------------
function edit-symlink () {
    if [ -z "$1" ]; then
        echo "Name of symbolic link you would like to edit:"
        read LINK
    else
        LINK="$1"
    fi
    LINKTMP="$LINK-tmp"
    if [ -z "$2" ]; then
        echo "Full destination path to update existing symlink with:"
        read DEST
    else
        DEST="$2"
    fi
    ln -s $DEST $LINKTMP
    rm $LINK
    mv $LINKTMP $LINK
    printf "Updated $LINK to point to new destination -> $DEST"
}
0
blizzrdof77

リンク名が(過去に)実行した結果として存在すると仮定します。

 ln -s   /the/path/to/a/file   linkname

次に、シンボリックリンクを変更する3つの方法があります。

  • Lnを-f forceで使用し、ディレクトリ-nでも使用します(inodeは再利用できます):

    ln -sfn /some/new/path linkname
    
  • シンボリックリンクを削除して、新しいものを作成します(ディレクトリの場合でも)。

    rm linkname; ln -s /some/new/path linkname
    
  • 新しいシンボリックリンクを作成し、次にmv it(ディレクトリの場合でもアトミック変更):

    ln -s  /some/new/path newlinkname
    mv -fT newlinkname linkname             # linkname remains after the command
    
0
Isaac