93

I have used ln to write symbolic links for years but I still get the order of parameters the wrong away around.

This usually has me writing:

ln -s a b

and then looking at the output to remind myself.

I always imagine to be a -> b as I read it when it's actually the opposite b -> a. This feels counter-intuitive so I find that I'm always second-guessing myself.

Does anyone have any tips to help me remember the correct order?

Zhro
  • 2,669
  • 13
    sometimes it help to say it outloud when you type it in "symbolic link to a, and call it b" – jsotola Sep 15 '19 at 01:13
  • 2
    You create the second parameter just like with cp, and you create the link. But if you get it the wrong way, no worries, because you cannot overwrite an existing file or symlink with a new link. – sudodus Sep 15 '19 at 14:33
  • 1
  • "man ln" is what I always do. – jamesqf Sep 16 '19 at 04:05
  • 3
    Think of it as a "bad guy's alias." He is always referred to by his real name first, then his aliases. Ex: Tony Baloney a.k.a. Oscar Meyer. Or in the case of your link, ln -s a b means "File-a is also known as File-b". – Scottie H Sep 16 '19 at 15:26
  • 7
    ln source target. Same as cp source target, mv source target; ... – user207421 Sep 17 '19 at 09:44
  • Easy. Run it the wrong way, see the error message or ls -l and delete the wrong link and run it the right way. – Kevin Sep 17 '19 at 20:27
  • use package tldr: tldr ln – qwr Sep 17 '19 at 21:48
  • Can you remember that it's the opposite of Windows' mklink command? – user1024 Sep 17 '19 at 22:19
  • The problem with opposites is that you have to remember something the right way around. That is the source of the problem. See my comment on @OhMyGoodness's answer. – Zhro Sep 17 '19 at 22:23
  • @qwr I'd never heard of the tldr package. What an adorable little tool. I suspect if you wanted to give someone a hard time then you could just alias this to man. – Zhro Sep 17 '19 at 22:24
  • i chant "TARGET, LINK NAME" to my self to remember the help text – cat Oct 12 '19 at 18:40
  • I constantly forget this. I forget what the command is even called and what the parameters are. I google it. I find the command quickly, but the example still leaves me wondering which one is the link and which one is the actual thing being linked to. Words like "target" and "source" don't clarify this for me, they just reinforce my confusion. – still_dreaming_1 Mar 23 '21 at 21:12
  • @still_dreaming_1 Relatable. Alternatives to the words "source" and "target" would probably help, but I have not come up with anything concise, yet. – Hermann Sep 07 '22 at 21:14
  • I finally made a function to reuse the args from a cp or mv:

    function lns { dir=$1; lastdir="${dir##*/}"; sudo ln -s $2/$lastdir $1; } # quick symlink using arg order from cp or mv

    "s" is for symbolic link, but lnh could be for hardlinks.

    – alchemy Apr 26 '23 at 20:31

13 Answers13

108

I go by "ln is like cp. The 'source' needs to come first."

Hermann
  • 6,148
  • 27
    ...and like mv. mv, cp and ln all take an existing file as first argument, and the intended destination file or directory name as second argument. – Hans-Martin Mosner Sep 15 '19 at 07:44
  • 7
    It's a shame that memcpy, strcpy etc. work the other way around. – Arkadiusz Drabczyk Sep 15 '19 at 13:53
  • 6
    @Hans-MartinMosner, except that when you create a symbolic link, it doesn't have to be an existing file... – ilkkachu Sep 15 '19 at 15:35
  • 1
    @ilkkachu You're right. No rule without exception :-) – Hans-Martin Mosner Sep 15 '19 at 16:03
  • 1
    @ArkadiuszDrabczyk On the other hand, something like memcpy(dest,src,n); maps very well to dest = src;. In other words, set (the first n bytes of) dest equal to (the first n bytes of) src. – user Sep 17 '19 at 12:39
  • 1
    Too bad this isn't universal ... if you just remember "The source needs to come first", when in a hurry, you'll easily go for: tar cvzf myImportantFileWitoutABackup.txt backup.tgz. And gone it is .... happened to me more than once. :-( – s1lv3r Sep 17 '19 at 13:34
  • 2
    @s1lv3r the arguments to tar are not positional. The path to the archive file is the parameter to the f(ile) option. – OrangeDog Sep 17 '19 at 15:34
  • 1
    Answers like this are why I waste so much time looking this up over and over again. The term "source" still leaves me questioning which one is which. Which one is just a link, and which one is the real thing being linked to? – still_dreaming_1 Mar 23 '21 at 21:14
  • @ still_dreaming_1 Yes, this answer confuses things when thinking the GNU way: When speaking about links "target" is the item that the link points to (based on GNU doc), so the first argument is the "target". Think about it in this way: ln -s $HOME creates a link to your home directory in the current directory. So optional second parameter defines where the link will be created at. I argue this answer is wrong, although it was made with the right intention in mind. It's a pitfall to compare a linked item to a copied item, because it makes thinks unclear depending how to think about "target". – Martin Braun Apr 26 '23 at 20:42
47

I use the following: ln has a one-argument form (2nd form listed in the manpage) in which only the target is required (because how could ln work at all without knowing the target) and ln creates the link in the current directory. The two-argument form is an addition to the one-argument form, thus the target is always the first argument.

gary
  • 724
  • 3
    Note that the form with no destination/target path is an extension to the POSIX specification of ln. – Kusalananda Sep 15 '19 at 18:18
  • 1
    @kusa: did you see the 1971 manual in my answer with the one-argument form? How can it be an extension to posix if it was there in 1971? --- "If name2 is given, the link has that name" –  Sep 15 '19 at 19:41
  • @S.P. I'm not sure I understand what you mean. Are you saying that a historical implementation somehow trumps the current POSIX standard? – Kusalananda Sep 15 '19 at 20:01
  • @kusa: Please consider linking to your source of reference. – gary Sep 15 '19 at 20:09
  • but why trumps? This Q is not about standads, but semantics, words and arrows. Of course history trumps when it comes to explaining the world. You should say "posix does not support one-argument form", and not: "that's [only] a gnu specific extension". Me I don't understand what you try to prove with the 6-to-1 list you put together. I think your conception is completely valid - I just prefer the other a bit more. Everybody else adds an idea and a joke. Just try once. –  Sep 15 '19 at 20:22
  • @gary Here. My comment was merely a reaction to your "ln has a one-argument form" bit, which should have said "ln often has a non-standard one-argument form". – Kusalananda Sep 15 '19 at 20:38
  • @S.P. I don't think I mentioned GNU in my comment. The extension (the one-argument form) is very common, but it's non-standard, so saying that ln has a one-argument form is not fully correct, unless you also specify what implementation you're looking at (e.g. the GNU coreutils implementation). My list, which is not pitting GNU against the others, is to show the source target semantics. I merely say that GNU uses other words for the arguments. – Kusalananda Sep 15 '19 at 20:41
  • 1
    I also see. Different names, same args, at least. I had no idea gnu is the only one with these arg names. –  Sep 15 '19 at 21:46
  • 2
    There were a lot of good answers here (expecially the rhyme by @loa_in_) but I'm going to go with this one. Stating that the order of parameters is consistent (ignoring -t) then it feels almost like a proof. "ln creates the link in the current directory. The two-argument form is an addition to the one-argument form and therefore the target is always the first argument". Because it makes sense that this would be the case when considering the second form, I think this will help me remember. – Zhro Sep 15 '19 at 23:55
  • The man page for ln says the target is the last parameter, not the first. So this answer is totally incorrect: ln [-L | -P | -s [-F]] [-f | -iw] [-hnv] source_file [target_file]. I think the confusion arrives from what people think of as the "target". The man page seems to think the target is the link being created. But I think most people think of the "target" as the existing file being targeted by the link (this is intuitive, the man page is not). – Michael Jun 24 '23 at 23:48
14

Most Unices document the ln command as

ln source target

(I'm omitting options etc. here)

Examples:

  • The POSIX standard

      ln [-fs] [-L|-P] source_file target_file
    
  • OpenBSD:

      ln [-fhLnPs] source [target]
    
  • NetBSD and FreeBSD

      ln [-L | -P | -s [-F]] [-f | -iw] [-hnv] source_file [target_file]
    
  • macOS

      ln [-Ffhinsv] source_file [target_file]
    
  • Solaris

      /usr/bin/ln [-fns] source_file [target]
    
  • AIX

      ln [ -f | -n ] [ -s ] SourceFile [ TargetFile ]
    

The GNU ln manual is the odd one out and calls the source target and the target linkname.

Ignoring the GNU choice of words, the ln utility follows the same semantics as, e.g. mv and cp in that the target is what is created from the source.

Therefore,

ln -s a b

would create the symbolic link b pointing to a. Or in other words, b is the target of the operation that creates a symbolic link using a as the source.

Note that when creating symbolic links, the source is simply a string representing what the symbolic link should point at. There is usually no check made to validate that it points to anything useful:

$ ln -s "hello world" README.txt
$ ls -l
total 0
lrwxr-xr-x  1 kk  wheel  11 Sep 15 11:39 README.txt -> hello world

A personal thought about GNU's choice to use "target" and "link name" rather than "source" followed by "target":

It may seem obvious that the second argument, the thing that is created, should be the "link name" and that the first argument, the target of the link, is "target". However, that's only true when you use the link.

When you create the link, which is what you're doing with ln, the second argument, the thing that is created, is the "target" of the ln operation, and it's created using the first argument, the "source".

This, together with the analogous "source"->"target" ordering of arguments to other basic tools, makes the non-GNU documentation for ln seem more natural.

Kusalananda
  • 333,661
  • 7
    I fully blame the GNU documentation for the fact that people get this wrong at all. Their wording is understandable in hindsight but objectively confusing. – Konrad Rudolph Sep 15 '19 at 12:11
  • 8
    @KonradRudolph, On the contrary, the GNU wording seems spot on to me. The utility creates a link with some name, pointing to somewhere. "Link name" is kinda obvious, and "target" is a perfectly good description for something that is pointed to. As an anecdote, I still have to sometimes think which way ln -s a b works, and that has nothing to do with the GNU wording, since I don't think I've ever looked at the phrasing in the man page. :D (It's easier to just run ln -si a b when not sure, it'll complain if b already exists.) – ilkkachu Sep 15 '19 at 17:22
  • 2
    @KonradRudolph, though technically, calling it "target" in the case of a hard link is wrong, since it's not the existing name but the inode that's the actual target. I wonder if the GNU folks thought that a common user shouldn't have to think of it in that much detail. – ilkkachu Sep 15 '19 at 17:24
  • It's interesting to point out, as mentioned in the comments of @gary's answer, that the target is not optional in the POSIX standard. – Zhro Sep 15 '19 at 23:42
  • @kusa: with "ln -s A B --- copy only the file's name to B " I have adopted your interpretation in a slightly changed context. I can even agree with your radical "hello world" example. "Only the file's name' IS a string. Just want to signal to you that I edited a bit and added a lot. –  Sep 16 '19 at 12:00
  • The names source and target are really confusing/misleading with ln since the "source" may not exist and the "target" could be interpreted as the target of the link (the file that will be acted on when you open the link) or the target of the command (the file, a link, which the command will create). Better naming (for symbolic links) would be "link contents" and "link name". – R.. GitHub STOP HELPING ICE Sep 16 '19 at 14:41
  • @R.. But ln is not opening the link, it's creating it. The target of the operation that is creating the link is the 2nd argument, using the source, the 1st argument, to say what the link should be. – Kusalananda Sep 16 '19 at 14:45
11

I recently heard a great way to remember this particular thing: a rhyme

Something old, something new,

something borrowed, something blue,

and a sixpence in her shoe.

The first verse is what the arguments of ln are: something old followed by a name of the new directory entry.

loa_in_
  • 398
  • 1
  • 9
7

In case this helps anyone: I've gotten used to thinking of it as "ln what where", which helps me remember that the first argument ("what") is the existing file, the second ("where") is the place to put (a link to) it. As opposed to the reasoning in most of the other answers, this is nothing more than a pithy phrase that I can mentally recite to myself as I'm typing a command, which serves as a memory aid. This probably won't be useful to everyone but I suspect that it will help some people.

It helps that the other standard file manipulation commands use the same convention, so I can do the same for cp and mv.

David Z
  • 912
  • 4
    I'm curious to get some idea of why this was downvoted. There's not much here that could be wrong - did I mix up the order or something? – David Z Sep 15 '19 at 14:04
  • I personally think that "ln what where" is still not unambiguous without the explanation: what could either be "what is the link pointing linking at?" (correct) or "what is linking to something?" (wrong). Same with where: "where is the link pointing to?" (wrong) or "where should the link be created" (correct). So this does not necessarily help that much if you are second-guessing yourself. Remembering cp and mv should help though. – 125_m_125 Sep 16 '19 at 17:00
  • We all expect a UNIX command to include its file arguments after other kinds of argument (like grep does, for exmaple). ln creates a file of a certain type with a given contents. That the filesystem does something special and we usually put the path to some source file in it is incidental to ln. For exmaple, I could write a text editor which stored the contents of its first line in a symlink called 1, etc. This would be daft but it emphasizes that ln creates some kind of file with some text contents, nothing more or less, and makes the argument order seem logical. – Dannie Sep 16 '19 at 17:19
  • @125_m_125 The alternate interpretation you presented doesn't make much sense to me, but that's okay; this memory aid isn't for everyone. – David Z Sep 16 '19 at 18:20
  • @DavidZ, well I didn't downvote you, but I read it as "what link, and where does it point" which is obviously not what you meant. ln follows the mv syntax more or less. From [usually] existing to non-existing. – tgm1024--Monica was mistreated Dec 22 '20 at 19:17
  • @tgm1024--Monicawasmistreated Sure, fair enough. I read it the opposite way, as "what file, and where should it be linked". This is why I say the memory aid isn't for everyone; it helps people who would naturally read it the way I do, but not people who naturally read it the way you do. – David Z Dec 22 '20 at 19:43
4
NAME    ln -- make a link
SYNOPSIS    ln name1[ name2 ]
DESCRIPTION ln creates a link to an existing file name1. 
            If name2 is given, the link has that name; 

From 1971 Unix First Edition Manuals.

There is a second, simple, syntax form.


I put FILE or FILENAME instead of TARGET --- see comments etc. See also very long addition at the bottom, addressing the iceberg, hard and soft of ln, not just the tip of it.


So GNU ln has this:

ln [opt] FILENAME

In the 2nd form, create a link to FILENAME in the current directory.

where you don't need the link name. After ln -s /usr/lib/modules you get a

modules -> /usr/lib/modules

with the same name as FILENAME ("target" or "source"), right where you are. No choice, no confusion.

Now if you are more demanding and want the link created under another name and/or somewhere else, you add that wish as name or path. The real target comes first, the extra fancy new link name second.


Or you say: "I know this arrow notation in ls -l for links. I don't have an arrow in the shell to show the direction of my link. So I have to turn it around."

You create it in one direction, so you can use it in the other.

(END OF ANSWER-THE-QUESTION PART)


On another level, the word "link" itself carries a deep hidden double meaning. Symbolic links came later, so in the early days a link was just a link. There was no soft and hard, no -s option. And now I even use the source-target symbolism:

mv    A B   --- move the whole file to B (dir or new name)
cp    A B   --- copy whole file (mv and cp are "the same" here)    
ln    A B   --- copy whole file MINUS data blocks (=copy only inode and name), and increase "link count" for track keeping

At this stage, there are links, but no hard and soft, and ls -l does not show arrows, because there is no direction in a (hard) link. A "link" at that stage of unix evolution meant that filename "B" (directory entry "B") in the filesystem points to the same inode as filename "A" is pointing to.

Files A and B are "linked" together, because they share the same blocks. So now with every rm, the kernel has to check: do I delete/free this file's blocks on the disk, or is there another file linked to the same blocks? For that, a link counter is used.

Say you want to keep a big file on /tmp from being deleted and do ln /tmp/bigfile. Now you have a large bigfile in your working dir. After cleaning /tmp and removing the "original", you happily go on using the same data blocks. You don't get a dead or dangling link, you have a normal file. Pointing to no file but only filesystem blocks as every dir entry does. Only now "cleaning" /tmp is not as effectve as it was. It looks empty, and it is, but the blocks on the partition don't get freed.

Even though a hard link does not cost space itself as cp does, it can indirectly.

Adding ln -s to the sequence above:

ln -s A B   --- copy only the file's name to "B"   

Now "B", the soft link, only has a string with a pathname. This is "soft" info. Technically "A" and "B" are unrelated. But still B is a "link" in the new sense that you can use that stored pathname as a shortcut to "A". Now it is "a link to A" (period) and not "linked with file A's inode"

Both kind of links can confuse not only humans but also the kernel/fs. The 1971 man page notes: "BUGS: links get backed up twice, and restored as separate files with separate inodes."

Hard links to directories (rare/not allowed) can easily lead to a clog.

Soft links to directories (very common) can lead to eternal loops - these have to be recognized by utilities / kernel.

Practical example in bash

Starting with a regular file "F"...

ln F Fhard

...makes Fhard the same size as F, but they BOTH appear now in a dark red WITHOUT arrows in ls -l --color. Because of stat showing "Links: 2" in connection with "Inode: xyz". Hard linking F turns F itself into a hard link. Both are/stay filetype "regular file". But both have an inode with a link count above 1.

   ln -s F Fsoft

...makes a tiny "unregular" file "Fsoft" with filetype "symbolic link" --- even more space saving than an empty dir. A ls -l shows nothing special for "F". For Fsoft, the shown size is 1 byte as the string is 'F', and Fsoft -> F is displayed as name. No need to colorize a soft link to recognize one, because in the short form ls -F you get a coiled chain @ appended: Fsoft@

With ls -l it looks like this:

-rw-r--r-- 2 root root 6070340 Sep 16 16:28 F
-rw-r--r-- 2 root root 6070340 Sep 16 16:28 Fhard
lrwxrwxrwx 1 root root       1 Sep 16 16:31 Fsoft -> F

Fhard has F's size and type.

Fsoft has F's name and F's name's length as size, and a different file type.

Short ls -sF:

5932 F    5932 Fhard     0 Fsoft@

adding --block-size=1 does not yield same sizes either. Fsoft has size "one byte, zero blocks". F and Fhard deviate in parallel:

6074368 F  6074368 Fhard    0 Fsoft@

To see whether Fsoft is dangling or not, ls lets you use colors.

ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file
Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
2

It is really helpful to remember that the name of the link is optional. If it is not given, the basename of the link target is used.

ln -s /path/to/file1 file1

is identical to dropping the link name completely:

ln -s /path/to/file1

This would not make any sense if the link target was mentioned last.

rexkogitans
  • 1,329
1

Just think Unix -> AT&T -> destination on right:

mov %eax, %ebx  ;; AT&T style assembler syntax: %ebx register gets value of %ecx

mv foo bar    ;; foo renamed to bar

cp foo bar    ;; contents of foo go to bar

foo | bar     ;; data moves left to right in pipeline

ln abc def    ;; link to abc installed as def
Kaz
  • 8,273
0

Similar to cp, which I mentally read as “copy this to that”, I read ln commands as “link this to that”.

jl6
  • 1,455
  • 2
  • 14
  • 29
0

Personally, I prefer to avoid remembering X, in favour of knowing where to look for X when I need it. I'm also a fan of the "better safe than sorry" attitude so I always like to check carefully what I'm writing, especially as root.

In this case, the answer is literally in the first lines of the manpage:

   ln [OPTION]... [-T] TARGET LINK_NAME
   (...)
   In the 1st form, create a link to TARGET with the name LINK_NAME.

I wouldn't have suggested it if it required to delve in the manpage, but since it's right at the beginning, IMHO it's worth the 3 seconds it takes to type man ln and quit.

dr_
  • 29,602
  • Only the GNU man page for ln document it as "[target] [linkName]". All other flavors document it as "[source] [target]". The problem is "target" is ambiguous. (the GNU man page makes the most sense IMHO) – Michael Jun 24 '23 at 23:59
-1

This is how I remember it: Forget the target. In other words, if I am in dir1 and want to create a symlink here to file1 that exists in /some/other/dir/, I would just do:

ln -s /some/other/dir/file1

You will get a symlink called file1 in dir1 that points to /some/other/dir/file1. From the man page for ln:

ln [OPTION]... TARGET (2nd form) ... In the 2nd form, create a link to TARGET in the current directory.

Just keep in mind that this work only if you want the symlink to have the same name as the target (which most likely is the case).

  • Can someone please explain why this was downvoted? I just copy-pasted from the man page (and accordingly attributed). It will help others to understand how to post on SE. Thanks. – Hopping Bunny Sep 18 '19 at 05:35
  • 1
    i can explain: it is a cultural clash. Don't worry. Check the other answers, comments... –  Sep 18 '19 at 07:13
-2

Imagine a version of ln which allowed you to create multiple (symbolic) links in one command.

Synopsis: ln -s TARGET NEW_LINK...
Example: ln -s target_file  new_link_1  new_link_2  new_link_3

It wouldn't make any since to reverse that, since a symlink can only point to one TARGET at a time and the normal command line convention is to put the repeating part at the end of the command line, e.g. grep PAT [FILE]...

jrw32982
  • 723
-3

I'd like to expand on @gary's answer.

In addition to his anwer: the ln command can accept arbitrary number of arguments, so that you can create multiple symlinks in one invocation (which is handy when you need it).

  1. With that knowledge, when you encounter ln -s foo bar baz, what's the most logical explanation which arguments means what?
  2. With the answer to #1, when you encounter ln -s foo bar, what's the most logical explanation which arguments means what?
yegle
  • 1,149
  • 1
    If you have an addition to gary's answer, please suggest it as an edit. As-is, your two trailing (hypothetical?) questions make this "Answer" look more like a second question. – Jeff Schaller Sep 17 '19 at 18:19