web-dev-qa-db-ja.com

コマンドラインからシンボリックリンクターゲットを見つける

私がシンボリックリンクを設定したとしましょう:

ln -s /root/Public/mytextfile.txt /root/Public/myothertextfile.txt

myothertextfile.txtのターゲットがコマンドラインを使用しているかどうかを確認する方法はありますか?

141
Jared

使用 -fフラグを使用して、正規化されたバージョンを出力します。例えば:

readlink -f /root/Public/myothertextfile.txt

man readlink

-f, --canonicalize
      canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
184
brian-brazil

readlinkは必要なコマンドです。コマンドのマニュアルページを確認する必要があります。実際のファイルへの一連のシンボリックリンクをたどる場合は、-eまたは-fスイッチが必要です。

$ ln -s foooooo zipzip   # fooooo doesn't actually exist
$ ln -s zipzip zapzap

$ # Follows it, but doesn't let you know the file doesn't actually exist
$ readlink -f zapzap
/home/kbrandt/scrap/foooooo

$ # Follows it, but file not there
$ readlink -e zapzap

$ # Follows it, but just to the next symlink
$ readlink zapzap
zipzip
25
Kyle Brandt

これも機能します:

ls -l /root/Public/myothertextfile.txt

ただし、readlinkは、lsを解析するのではなく、スクリプトで使用することをお勧めします。

リンクのソースとリンク先を表示する場合は、stat -c%N files*を試してください。例えば。

$ stat -c%N /dev/fd/*
‘/dev/fd/0’ -> ‘/dev/pts/4’
‘/dev/fd/1’ -> ‘/dev/pts/4’

解析には適していません(そのためにはreadlinkを使用してください)が、ls -lの混乱なくリンク名とリンク先が表示されます

-cと記述できます--formatおよび%Nは、「シンボリックリンクの場合、逆参照付きの引用符で囲まれたファイル名」を意味します。

5
Robert Siemer

readlinkは良いことですが、GNU固有でクロスプラットフォームではありません。以前は/bin/shのクロスプラットフォームスクリプトを作成していたため、次のようなものを使用します。

 ls -l /root/Public/myothertextfile.txt | awk '{print $NF}'

または:

 ls -l /root/Public/myothertextfile.txt | awk -F"-> " '{print $2}'

ただし、これらは異なるプラットフォームでテストする必要があります。私はそれらはうまくいくと思いますが、ls出力フォーマットについて100%確信が持てません。

lsの結果は、bashawksedなどの外部コマンドに依存することなく、Perl内で解析することもできます。

このbash_realpath関数は、リンクの最終的な宛先を解決します(リンク→リンク→リンク→最終):

bash_realpath() {
  # print the resolved path
  # @params
  # 1: the path to resolve
  # @return
  # >&1: the resolved link path

  local path="${1}"
  while [[ -L ${path} && "$(ls -l "${path}")" =~ -\>\ (.*) ]]
  do
    path="${BASH_REMATCH[1]}"
  done
  echo "${path}"
}

質問は、ブライアンブラジルの質問のように単純な答えを出すには十分正確ではありません。

readlink -f some_path

確かに逆参照になりますすべてのシンボリックリンクsome_pathの後ろの最終ターゲットへのパス構成で。

ただし、カスケードシンボリックリンクの1つのレベルは、システム内の特定のケースにすぎず、一般的なケースはNレベルのカスケードシンボリックリンクです。私のシステムで以下を見てください:

$ rwhich emacs
/usr/bin/emacs
 /etc/alternatives/emacs
  /usr/bin/emacs24-x

rwhichは、whichの私自身の再帰的な実装であり、中間ターゲットのすべてのカスケードシンボリックリンク(stderrへ)を最終ターゲット(stdoutへ)に出力します。

次に、私が何であるかを知りたい場合:

  • symlinkのターゲット/usr/bin/emacs **、私への明白な答えは/etc/alternatives/emacsです。

    readlink $(which emacs)
    readlink /usr/bin/emacs
    
  • thefinalカスケードシンボリックリンクの背後にあるターゲット/usr/bin/emacs、答えは/usr/bin/emacs24-xになります:

    readlink -f $(which emacs)
    readlink -f /usr/bin/emacs
    rwhich emacs 2>/dev/null
    
1
Nico

readlinkを使用できない場合、ls -lの結果の解析は次のように行うことができます。

通常の結果は次のようになります。

ls -l /root/Public/myothertextfile.txt
lrwxrwxrwx 1 root root 30 Jan  1 12:00 /root/Public/myothertextfile.txt -> /root/Public/mytextfile.txt

そのため、「->」の前にあるすべてのものと、含まれている矢印を置き換えます。これにはsedを使用できます。

ls -l /root/Public/myothertextfile.txt | sed 's/^.* -> //'
/root/Public/mytextfile.txt
1
7ochem

llまたはls -lは、シンボリックリンクとそのターゲットを含むディレクトリ項目をリストする必要があります

cd -P /root/Public/myothertextfile.txt(あなたの場合)は元のパスを指す必要があります

0
Mantz

フォルダーとそのサブフォルダー内のすべてのリンクのターゲットが見つかった場合は、find . -type l -lsコマンドとリンクタイプは次のとおりです。

[email protected]:~/test$ find . -type l -ls
8601855888        0 lrwxr-xr-x    1 me           staff                   6 Jan 24 19:53 ./link -> target

シングルのターゲットが必要な場合は、ls -lは動作するはずです:

[email protected]:~/test$ ls -l 
total 0
lrwxr-xr-x  1 me  staff  6 Jan 24 19:53 link -> target
-rw-r--r--  1 me  staff  0 Jan 24 19:53 target
0
Memin