TL;DR: ln -T
I was refactoring more my Nix config, and specifically replacing my link farm with nix as described in my previous post.
When I noticed that links were being created in the wrong places. I would run
ln more than once and would get links in random locations:
$ ln -vfs "$DOTFILE_FOLDER/nvim/" "$HOME/.config/nvim"
'/home/nobe4/.config/nvim' -> '/home/nobe4/dev/nobe4/dotfiles/nvim'
$ ls -la "$HOME/.config/nvim"
lrwxrwxrwx 1 nobe4 users 35 Feb 4 20:12 /home/nobe4/.config/nvim -> /home/nobe4/dev/nobe4/dotfiles/nvim
# all good!
# do some testing ...
$ ln -vfs "$DOTFILE_FOLDER/nvim/" "$HOME/.config/nvim"
'/home/nobe4/.config/nvim/nvim' -> '/home/nobe4/dev/nobe4/dotfiles/nvim'
# uh, what now?
$ ls -la $DOTFILE_FOLDER/nvim/nvim
lrwxrwxrwx 1 nobe4 users 35 Feb 4 20:12 /home/nobe4/dev/nobe4/dotfiles/nvim/nvim -> /home/nobe4/dev/nobe4/dotfiles/nvim
# what the hellIn a simplified form:
$ mkdir a
$ ln -vfs a b
'b' -> 'a'
$ ln -vfs a b
'b/a' -> 'a'
$ tree
.
βββ a
β βββ a -> a
βββ b -> aThat prompted me to do an overly zealous study of what ln do in various
scenario. The conclusion of this post is everyone’s favorite: RTFM.
The test scenario ΒΆ
All the commands are ran with:
link () {
ln --verbose --force --symbolic "$(pwd)/${1:?}" "$(pwd)/${2:?}"
}$1is the target, what the link points to.$2is link name, but not always, it is sometimes the directory.
Legend
- οΏ½: Missing File, Directory, or Link.
- F: File
- D: Directory
- FL: Link to a File
- DL: Link to a Directory
- οΏ½FL: Broken link to a File
- οΏ½DL: Broken link to a Directory
/: Ends with a/
$1 \ $2 | οΏ½ | F | D |
|---|---|---|---|
| οΏ½ | 0 β | 14 β | 28 β |
οΏ½/ | 1 β | 15 β | 29 β |
| F | 2 β
| 16 β
| 30 β οΈ |
F/ | 3 β | 17 β | 31 β |
| D | 4 β
| 18 β
| 32 β οΈ |
D/ | 5 β
| 19 β
| 33 β οΈ |
| οΏ½FL | 6 β | 20 β | 34 β |
οΏ½FL/ | 7 β | 21 β | 35 β |
| FL | 8 β
| 22 β
| 36 β οΈ |
FL/ | 9 β | 23 β | 37 β |
| οΏ½DL | 10 β | 24 β | 38 β |
οΏ½DL/ | 11 β | 25 β | 39 β |
| DL | 12 β
| 26 β
| 40 β οΈ |
DL/ | 13 β
| 27 β
| 41 β οΈ |
Notes:
The indexes correspond to the test results listed below.
Results:
- β : the link is valid
- β: the link is broken
- β οΈ: the link exists but might not be what you want
β οΈ: All the links are created inside the directory, rather than being the directory.
E.g. for the same command
link a b:# instead of ### [16] ### . βββ a βββ b -> /tmp/ln/a # we get ### [30] ### . βββ a βββ b βββ a -> /tmp/ln/aThis is what
man lncalls the3rd and 4th forms:In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
If you look back before the table, that’s what the “sometimes” means for
$2.
Full test results
run.sh#!/usr/bin/env bash link () { ln --verbose --force --symbolic "$(pwd)/${1:?}" "$(pwd)/${2:?}" } clean() { find . -not -name run.sh -delete ; } run() { echo -e "\n### [${id}] ###: $1" eval "$1" tree -I 'run.sh' | head -n -2 find . -xtype l -exec echo "Broken link: {}" \; id=$((id + 1)) clean } id=0 cases=( # column 1 "link a b" "link a/ b" "touch a && link a b" "touch a && link a/ b" "mkdir a && link a b" "mkdir a && link a/ b" "link a b && link b c" "link a b && link b/ c" "touch a && link a b && link b c" "touch a && link a b && link b/ c" "link a/ b && link b c" "link a/ b && link b/ c" "mkdir a && link a b && link b c" "mkdir a && link a b && link b/ c" # column 2 "touch b && link a b" "touch b && link a/ b" "touch b && touch a && link a b" "touch b && touch a && link a/ b" "touch b && mkdir a && link a b" "touch b && mkdir a && link a/ b" "touch c && link a b && link b c" "touch c && link a b && link b/ c" "touch c && touch a && link a b && link b c" "touch c && touch a && link a b && link b/ c" "touch c && link a/ b && link b c" "touch c && link a/ b && link b/ c" "touch c && mkdir a && link a b && link b c" "touch c && mkdir a && link a b && link b/ c" # column 2 "mkdir b && link a b" "mkdir b && link a/ b" "mkdir b && touch a && link a b" "mkdir b && touch a && link a/ b" "mkdir b && mkdir a && link a b" "mkdir b && mkdir a && link a/ b" "mkdir c && link a b && link b c" "mkdir c && link a b && link b/ c" "mkdir c && touch a && link a b && link b c" "mkdir c && touch a && link a b && link b/ c" "mkdir c && link a/ b && link b c" "mkdir c && link a/ b && link b/ c" "mkdir c && mkdir a && link a b && link b c" "mkdir c && mkdir a && link a b && link b/ c" ) for t in "${cases[@]}"; do run "$t" doneOutput
### [0] ###: link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ b -> /tmp/ln/a Broken link: ./b ### [1] ###: link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ b -> /tmp/ln/a/ Broken link: ./b ### [2] ###: touch a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [3] ###: touch a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ Broken link: ./b ### [4] ###: mkdir a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [5] ###: mkdir a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ ### [6] ###: link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [7] ###: link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [8] ###: touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [9] ###: touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c ### [10] ###: link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [11] ###: link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [12] ###: mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [13] ###: mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ ### [14] ###: touch b && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ b -> /tmp/ln/a Broken link: ./b ### [15] ###: touch b && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ b -> /tmp/ln/a/ Broken link: ./b ### [16] ###: touch b && touch a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [17] ###: touch b && touch a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ Broken link: ./b ### [18] ###: touch b && mkdir a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [19] ###: touch b && mkdir a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ ### [20] ###: touch c && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [21] ###: touch c && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [22] ###: touch c && touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [23] ###: touch c && touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c ### [24] ###: touch c && link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [25] ###: touch c && link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [26] ###: touch c && mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [27] ###: touch c && mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ ### [28] ###: mkdir b && link a b '/tmp/ln/b/a' -> '/tmp/ln/a' . βββ b βββ a -> /tmp/ln/a Broken link: ./b/a ### [29] ###: mkdir b && link a/ b '/tmp/ln/b/a' -> '/tmp/ln/a/' . βββ b βββ a -> /tmp/ln/a/ Broken link: ./b/a ### [30] ###: mkdir b && touch a && link a b '/tmp/ln/b/a' -> '/tmp/ln/a' . βββ a βββ b βββ a -> /tmp/ln/a ### [31] ###: mkdir b && touch a && link a/ b '/tmp/ln/b/a' -> '/tmp/ln/a/' . βββ a βββ b βββ a -> /tmp/ln/a/ Broken link: ./b/a ### [32] ###: mkdir b && mkdir a && link a b '/tmp/ln/b/a' -> '/tmp/ln/a' . βββ a βββ b βββ a -> /tmp/ln/a ### [33] ###: mkdir b && mkdir a && link a/ b '/tmp/ln/b/a' -> '/tmp/ln/a/' . βββ a βββ b βββ a -> /tmp/ln/a/ ### [34] ###: mkdir c && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b Broken link: ./c/b Broken link: ./b ### [35] ###: mkdir c && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b/ Broken link: ./c/b Broken link: ./b ### [36] ###: mkdir c && touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b ### [37] ###: mkdir c && touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b/ Broken link: ./c/b ### [38] ###: mkdir c && link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c/b' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a/ βββ c βββ b -> /tmp/ln/b Broken link: ./c/b Broken link: ./b ### [39] ###: mkdir c && link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c/b' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a/ βββ c βββ b -> /tmp/ln/b/ Broken link: ./c/b Broken link: ./b ### [40] ###: mkdir c && mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b ### [41] ###: mkdir c && mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c/b' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c βββ b -> /tmp/ln/b/
The problem ΒΆ
Going back to my initial scenario:
$ ln -vfs "$DOTFILE_FOLDER/nvim/" "$HOME/.config/nvim"We now understand the weird behavior:
First run, the
$HOME/.config/nvimlink is created, it points to the directory$DOTFILE_FOLDER/nvim/.$HOME/.config/nvim -> $DOTFILE_FOLDER/nvimSecond run,
lnsees a directory, and assumes that you want to link into the directory, rather than link the directory.$DOTFILE_FOLDER/nvim/nvim -> $HOME/.config/nvim -> $DOTFILE_FOLDER/nvimThe result is a new link inside the linked directory:
$DOTFILE_FOLDER/nvim/nvim -> $DOTFILE_FOLDER/nvim
The solution ΒΆ
Per usual, RTFM:
-T, --no-target-directory
treat LINK_NAME as a normal file alwaysThis means that no matter what LINK_NAME is, it always takes as the name of
the link, never the directory in which to put the link.
Using this new flag:
$ ln -vfsT "$DOTFILE_FOLDER/nvim/" "$HOME/.config/nvim"
'/home/nobe4/.config/nvim' -> '/home/nobe4/dev/nobe4/dotfiles/nvim'
$ ls -la "$HOME/.config/nvim"
lrwxrwxrwx 1 nobe4 users 35 Feb 4 20:12 /home/nobe4/.config/nvim -> /home/nobe4/dev/nobe4/dotfiles/nvim
# all good!
# do some testing ...
$ ln -vfsT "$DOTFILE_FOLDER/nvim/" "$HOME/.config/nvim"
'/home/nobe4/.config/nvim' -> '/home/nobe4/dev/nobe4/dotfiles/nvim'
# looking good!
$ ls -la $DOTFILE_FOLDER/nvim/nvim
ls: cannot access '/home/nobe4/dev/nobe4/dotfiles/nvim/nvim': No such file or directory
# yeeeIn a simplified form:
$ mkdir a
$ ln -vfsT a b
'b' -> 'a'
$ ln -vfsT a b
'b' -> 'a'
$ tree
.
βββ a
βββ b -> aThe new test scenario ΒΆ
All the commands are ran with:
link () {
ln --verbose --force --symbolic --no-target-directory "$(pwd)/${1:?}" "$(pwd)/${2:?}"
}$1 \ $2 | οΏ½ | F | D |
|---|---|---|---|
| οΏ½ | 0 β | 14 β | 28 π₯ |
οΏ½/ | 1 β | 15 β | 29 π₯ |
| F | 2 β
| 16 β
| 30 π₯ |
F/ | 3 β | 17 β | 31 π₯ |
| D | 4 β
| 18 β
| 32 π₯ |
D/ | 5 β
| 19 β
| 33 π₯ |
| οΏ½FL | 6 β | 20 β | 34 π₯ |
οΏ½FL/ | 7 β | 21 β | 35 π₯ |
| FL | 8 β
| 22 β
| 36 π₯ |
FL/ | 9 β | 23 β | 37 π₯ |
| οΏ½DL | 10 β | 24 β | 38 π₯ |
οΏ½DL/ | 11 β | 25 β | 39 π₯ |
| DL | 12 β
| 26 β
| 40 π₯ |
DL/ | 13 β
| 27 β
| 41 π₯ |
Notes:
- Results:
Same as before
π₯: The command fail with
Cannot overwrite directory.This happens for the entire column, because the directory already exists and
lndoes not override it if it’s supposed to be a normal file.To get a valid link the full path must be specified, inside the directory.
E.g.
$ mkdir a b $ link a b ln: /tmp/ln/b: cannot overwrite directory $ link a b/a '/tmp/ln/b/a' -> '/tmp/ln/a' $ tree . βββ a βββ b βββ a -> /tmp/ln/a
Full test results
run.shlink () { - ln --verbose --force --symbolic "$(pwd)/${1:?}" "$(pwd)/${2:?}" + ln --verbose --force --symbolic --no-target-directory "$(pwd)/${1:?}" "$(pwd)/${2:?}" }Output
### [0] ###: link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ b -> /tmp/ln/a Broken link: ./b ### [1] ###: link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ b -> /tmp/ln/a/ Broken link: ./b ### [2] ###: touch a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [3] ###: touch a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ Broken link: ./b ### [4] ###: mkdir a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [5] ###: mkdir a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ ### [6] ###: link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [7] ###: link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [8] ###: touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [9] ###: touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c ### [10] ###: link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [11] ###: link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [12] ###: mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [13] ###: mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ ### [14] ###: touch b && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ b -> /tmp/ln/a Broken link: ./b ### [15] ###: touch b && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ b -> /tmp/ln/a/ Broken link: ./b ### [16] ###: touch b && touch a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [17] ###: touch b && touch a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ Broken link: ./b ### [18] ###: touch b && mkdir a && link a b '/tmp/ln/b' -> '/tmp/ln/a' . βββ a βββ b -> /tmp/ln/a ### [19] ###: touch b && mkdir a && link a/ b '/tmp/ln/b' -> '/tmp/ln/a/' . βββ a βββ b -> /tmp/ln/a/ ### [20] ###: touch c && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [21] ###: touch c && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [22] ###: touch c && touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [23] ###: touch c && touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ Broken link: ./c ### [24] ###: touch c && link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b Broken link: ./c Broken link: ./b ### [25] ###: touch c && link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ b -> /tmp/ln/a/ βββ c -> /tmp/ln/b/ Broken link: ./c Broken link: ./b ### [26] ###: touch c && mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b ### [27] ###: touch c && mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' '/tmp/ln/c' -> '/tmp/ln/b/' . βββ a βββ b -> /tmp/ln/a βββ c -> /tmp/ln/b/ ### [28] ###: mkdir b && link a b ln: /tmp/ln/b: cannot overwrite directory . βββ b ### [29] ###: mkdir b && link a/ b ln: /tmp/ln/b: cannot overwrite directory . βββ b ### [30] ###: mkdir b && touch a && link a b ln: /tmp/ln/b: cannot overwrite directory . βββ a βββ b ### [31] ###: mkdir b && touch a && link a/ b ln: /tmp/ln/b: cannot overwrite directory . βββ a βββ b ### [32] ###: mkdir b && mkdir a && link a b ln: /tmp/ln/b: cannot overwrite directory . βββ a βββ b ### [33] ###: mkdir b && mkdir a && link a/ b ln: /tmp/ln/b: cannot overwrite directory . βββ a βββ b ### [34] ###: mkdir c && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ b -> /tmp/ln/a βββ c Broken link: ./b ### [35] ###: mkdir c && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ b -> /tmp/ln/a βββ c Broken link: ./b ### [36] ###: mkdir c && touch a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ a βββ b -> /tmp/ln/a βββ c ### [37] ###: mkdir c && touch a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ a βββ b -> /tmp/ln/a βββ c ### [38] ###: mkdir c && link a/ b && link b c '/tmp/ln/b' -> '/tmp/ln/a/' ln: /tmp/ln/c: cannot overwrite directory . βββ b -> /tmp/ln/a/ βββ c Broken link: ./b ### [39] ###: mkdir c && link a/ b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a/' ln: /tmp/ln/c: cannot overwrite directory . βββ b -> /tmp/ln/a/ βββ c Broken link: ./b ### [40] ###: mkdir c && mkdir a && link a b && link b c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ a βββ b -> /tmp/ln/a βββ c ### [41] ###: mkdir c && mkdir a && link a b && link b/ c '/tmp/ln/b' -> '/tmp/ln/a' ln: /tmp/ln/c: cannot overwrite directory . βββ a βββ b -> /tmp/ln/a βββ c
Conclusion ΒΆ
-T’s behavior reminds me a lot of the JavaScript’s ===: it’s the most
logical to me, and yet not the default behavior.
But also, RTFM.