その繋がりは,嘘です.幻想です. 〜 `ls` と相対パス
ひさしぶり.だ.
この度は,ln
コマンドに関するメモです.
リンクを作成するアレですね.
今更ln
かよ,と言われていそうですが,えぇ,この話は,まさにその"今更"でした.
こんなエラーに出逢いました.
ln: <File Name>: File exists
以降の話の為にman ln
の内容を引用しておこうかと思います.;
SYNOPSIS ln [-Ffhinsv] source_file [target_file] : DESCRIPTION The ln utility creates a new directory entry (linked file) which has the same modes as the original file. :
ln
自身のこれ以上の詳細については,割愛.*1
という事で,この度
相対パスでln
を扱う場合,第1引数(source_file
)のパスは,第2引数(target_file
)側をカレントとして定義しなくてはならない
もしかして,"カレント"って言う表現はちょっと適切じゃないかな...?
ln
コマンドで指定する第一引数..は、symlinkを貼るディレクトリから見たパスを指定するので、..
今回の内容はこれに限る.
もうね,無知ってね,アレですね.あーやだ.
% sw_ver sw_vers is correct? [n,y,a,e]: y ProductName: Mac OS X ProductVersion: 10.15.7 BuildVersion: 19H15
いい加減,OS,アップグレードしなくちゃなぁ.
自分のイメージを自分の言葉で言語化しますと.
ln
を,相対パスで利用した場合,
パスは,
「source_file
のリンクをtarget_file
に...」と言うよりは,
「symlinktarget_file
は,source_file
から...」なイメージで捉えた方が良い.のかも.
sylink側から,source_file
を捉える感覚と言うか...
は?笑
こんな仕様があることを知った時,今まで知らずにln
を使っていた自分にちょっとゾッとした.
その後改めて,"ln 相対パス"等でググったら,まぁ出てくる出てくる.
しかも随分と過去の議論のようで...
あぁダメだ.
自嘲的な気分でいっぱい.
切っ掛け
ここで大変恐縮なのですが,さらにもうちょっと背景やら経緯をメモさせていただきたいと思います.
申し訳ございません.*2
震源地 ~ ln
"File exists" のスクリプト
作業を始めるにあたって,軽く振る舞いを見てみたいな,と思って用意した小さいスクリプト.
それはそれは実に稚拙な内容のスクリプトで,
結構に恥ずかしいレベルの内容なのですが,
これからの話のために,ありのまま晒しておこうかと思います.
ちなみに,これは間違ったスクリプトです.
説明のために. ;
#!/bin/bash -eu SOURCE="" DESTINATION="bkup" LATEST="Latest" readonly DATE_FORMAT=$(date "+%H-%M-%S") if [[ ! -e "$DESTINATION/$DATE_FORMAT" ]] ; then mkdir -p "$DESTINATION/$DATE_FORMAT" fi if [[ -e "$DESTINATION/$LATEST" ]] ; then rm "$DESTINATION/$LATEST" fi ln -s "$DESTINATION/$DATE_FORMAT" "$DESTINATION/$LATEST" echo "done."
一応.
このスクリプトを走らせる度に,
DESTINATION
で定義したスペースに,DATE_FORMAT
と言うディレクトリを作成し,
作ったディレクトリを最新アイテムとして,ln
でLATEST
と言う名前で,symlinkを生成する.
でも作らない笑
File exists
エラー.
んなもんです.
何かすみません.
そして実は...
最初に疑ったのは,test
コマンドだったりするのです.
おい,どこに行く...
情弱のなせる技.
symlink... ん?(二度見😳)
確認してみます.;
% ll ./bkup total 0 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-01 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-18 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-39 lrwxr-xr-x 1 woowee staff 13 7 6 20:47 Latest -> bkup/20-47-01
最後の行.
ファイル属性は,1文字目がl
,
そしてtargetLatest
とsourcebkup/20-47-01
が->
で結ばれている,ということでsymlinkは出来ているっぽい?
ただ.
source側がbkup/20-47-01
のまま.
さっっぱり分からない.
自分のレベルだと,まずここまでで,「なぜsymulinkbkup/Latest
あるのに,test
は識別して削除するロジックに落としてくれないのさ...」となる.
なんとも稚拙な解析力.
「なぜ消さない」
情弱の暴走が発動します.
-e
オプション調べる.;
$ test -e bkup/Latest ; echo $? 1
い,...いち..
「存在しません」と判断し,rm
の処理に落ちないのは,
正しい振る舞いだったわけですね.
じゃぁ,そのbkup/Latest
は何なのさ.
-L
オプションがあるのを思い出した
この作業でリファレンスしたコードは,確か-L
オプションを使っていたはず.
$ test -L bkup/Latest ; echo $? 0
あ.*3
manpageにも書いてますね.
-L file True if file exists and is a symbolic link.
「存在し,シンボリックリンクだったら,真」.
存在も見ている,ってことで良いのでしょうか.
-e
が見ている存在と何が違うのだろうか,と何んか附に落ちませんが.
という事で,オプションを大人しく-L
にする.
当該箇所のみ引用しますと,こんな感じです.;
... # if [[ -e "$DESTINATION/$LATEST" ]] ; then # -eオプションではなく, if [[ -L "$DESTINATION/$LATEST" ]] ; then # -Lオプションを使う rm "$DESTINATION/$LATEST" fi ...
うまく行くみたい.
ln: bkup/Latest: File exists
というエラーを吐くことはなく,結果を覗くと.;
% ll bkup/ total 0 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-01 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-18 drwxr-xr-x 2 woowee staff 64 7 6 20:47 20-47-39 drwxr-xr-x 2 woowee staff 64 7 6 21:00 21-00-07 lrwxr-xr-x 1 woowee staff 13 7 6 21:00 Latest -> bkup/21-00-07
source_file
の方も,最も新しいbkup/21-00-07
からリンクが貼られています.
-e
を使っていたときは,ずっと20-47-01
でした.
上手く行った?
オプションのようだった.
めでたしめでたし.
どれどれ...と.;
% cd Latest
cd:cd:1: no such file or directory: Latest
ん,ん?
何の気なしに,Finderで覗いて見た.;
ん?
アイコン,しろ?
とにかく,おかしいのは,わかった.
それは幻です
やっとこの辺りで気付きます.
そのsymlink,実はsymlinkじゃない,と言う,事実.😌
% stat -L bkup/Latest
stat: bkup/Latest: stat: No such file or directory
?...
stat
の使い方良く分かりません.
% file bkup/Latest bkup/Latest: broken symbolic link to bkup/05-08-46
file
コマンド,「それ,壊れてますよ」と.
この辺りでやっと気づきました.
test
コマンドは,見当違い
test
コマンドが,ファイル壊すわけありません笑
"lnコマンド 注意"あたりで検索したら,相対パスのトピックが目に入り.
"lnコマンド 相対パス"とかで調べたら,...出るわ出るわ.
しかも結構前に,語り尽くされた感あり.
ここでも,置いていかれている感に打ちひしがれる.何周遅れなん.prz
そんな感じで
ln
コマンドで相対パスを使った場合の問題であることを,やっとここで知るわけです.
#!/bin/bash -eu SOURCE="" DESTINATION="bkup" LATEST="Latest" readonly DATE_FORMAT=$(date "+%H-%M-%S") if [[ ! -e "$DESTINATION/$DATE_FORMAT" ]] ; then mkdir -p "$DESTINATION/$DATE_FORMAT" fi if [[ -e "$DESTINATION/$LATEST" ]] ; then # 結局 -e オプションでも良い # if [[ -L "$DESTINATION/$LATEST" ]] ; then rm "$DESTINATION/$LATEST" fi ln -s "./$DATE_FORMAT" "$DESTINATION/$LATEST" # 問題はここ,source_file 側の定義の仕方 echo "done."
そして.;
知らなかったなぁ,知らないままln
コマンド使っていたなぁ,交通ルールを知らないまま運転してたようなもんだ...なんぞ思いながら片づけをしていたら.
-r
オプションだってさっ
-r オプション最強
この目的のためにあるのが、r オプションln -sr で解決
相対パスを自動て解決してくれるのが -r オプション。まじでコレ付けるだけで解決する魔法のオプション
これ見て胸が膨らんだのですが,どうやらlinuxの話らしく,こちらのmanpageにはr
オプションの記載はありませんでした.BSDにはないみたいです.
はいおしまい.
結構書いたな,おい.