`$ ln -s link_from link_to` would imply the reverse behavior. How does a symlink point from the actual file to the thing-that-looks-like-a-file-but-is-really-a-symlink? The file doesn't even know whether there are symlinks pointing to it.
Applying your definitions of "link from" and "link to", this:
creates a link from google.com to the hyperlink on your site.
I find the top reddit comment:
cp existing new
ln -s existing new
much, much more useful. You want to create a new link pointing to an existing file, which has the same ordering as when you use cp to create a new file with the content of an existing file.
The problem with "from" and "to" is - which is the from and which is the to?
Is the "from" the file/dir I want to copy "to" a link?
Or is the "from" the name of a link I want to point "to"?
The dual meaning of some terms that the concept of links and making links creates causes a lot of this confusion, IMHO. Are we using terminology that refers to the act of creating the link or that refers to the direction of the link?
Similarly, I don't think it helps that the usage text and manpage for ln refer to "target"s.
(I know what you mean by your examples but I wanted to share my pet theory as to why this is always so hard to remember)
Exactly! The rule is for that commands of two letters in length (cp, ln, mv) the file on the end is the one that gets created. For commands of three letters in length (tar, zip) the file that gets created is the first one. And then there's the exceptions that prove the rule like scp and ssh.
I used to just cheat. I normally cd-ed to the directory I wanted the link in then just let the name of the link be the name of the file, so I didn't need a destination file name, just ln -s source_file
Exactly. Why the GP's comment is currently at +33 when all it does is restate the main point of the story in a confusing way (by introducing from/to into the mix) is beyond me.
Probably because most of the people upvoting him didn't bother to read the story.
I am often guilty of this myself. At first I used to read all of the stories that were linked to on HN, along with the comments. But I quickly learned that the comments were often much more interesting/useful than the stories themselves.
So now I just look at the comments first, by default. And only in exceptional cases do I actually bother to read the article. There's just not enough time..
HN is an overwhelming firehose of information even without reading every article that seems interesting. But reading the comments can usually quickly give you a good feel for whether the story is worth reading or not. In this particular case, I think not.
Does anyone know why C calls like 'strcpy' and 'strcat' are the opposite of this?
strcat(target, source)
strcpy(target, source)
But, in SH...
cp source target
I feel like these things were developed around the same time, by the same community. I've always wondered if there was a reason for the different perspective.
The reason strcat, strcpy have the destination first is because of the need to support a variable number of arguments. By definition, if the number of arguments is variable, they must be at the end. So if you think of sprintf for instance, the destination has to be first. Now, to be consistent, strcat has to behave the same and have the destination first as well, although it doesn't have a variable number of arguments.
I'm pretty sure strcpy et al pre-date the introduction of varargs. Besides, there's no reason the format string couldn't be the last argument of printf, except the specific technical detail that C requires at least one mandatory argument in any variadic function (the variable's address is used to locate the optional arguments in the stack.)
On a machine's runtime stack, there is no indication of how many parameters were passed to the function (at least on x86). C functions must use one of the mandatory arguments to determine how many arguments were pushed on the stack. In the case of the printf-family of functions, it's the number of format specifiers, e.g., "%d".
Someone once said to "What you have, then what you want" which made ALL of these easier to remember for me. In the case of strcat/cpy I think it still follows: I have an empty string 'target' and I'd like it to be 'source'.
Which is really the odd ball. In a left-to-right language, it's sort of bizarre that we don't write `4 = x' since the rvalue tends to be the more complicated part of the expression.
The curious bit is, AT&T assembly syntax does follow this convention so you'll see something like `mov $5, ax'.
This is a crime against usability IMO. Another comment mentioned that tar takes arguments as "target source" rather than "source target".
Ever notice that for everything in the world that screws, like valves or screws or bottle caps, counter-clockwise loosens and clockwise tightens? How is it we got the whole world to agree on that convention, but software is 50/50 on how we order the source and destination?
Propane tanks also used to have backwards screwing connections. I believe this was a safety 'feature' given the mainstream use of small propane tanks. Having them tighten counter-clockwise prevents similar looking but wrong hoses from being attached to the tank. It also tricked people who didn't understand propane tanks form being able to remove a connection (since they would usually just tighten it further).
Cars generally still do have backwards nuts on the LHS. Something about vibration and direction of turn. Some of the other bolts on the LHS can be that way too.
Same with some of the LP gas cylinders I have encountered here in Aus.
I have heard that other manufacturers originally starting using reverse-thread propane fittings to work around a 1896 Primus patent, and the situation has simply persisted.
And sometimes doorknobs, but those are abstract enough you wouldn't expect them to behave the same. Unless you're talking about screwing the dial itself clean off.
C calls are trying to mirror the assignment statement in the programming language:
target := source
"cp" is trying mirror how we do things in real life: if you want to take some things from one place and put them in another, you first pick them all up (hence the first argument), walk over to the destination, and then put them down.
It comes from assignment syntax where the left hand side is the target of the assignment and the right hand side is the source. So this makes a ton of sense in C.
OTOH, the Bourne shell was built independent of the C programming language. The Bourne shell inherited a bit from its predecessor the Thompson shell which introduce the concept of command piping. In this case, all operations followed the pattern of data flowing to the right. This is the opposite of how assignment works in all programming languages where data flows to the left.
That's why shell commands generally move data from left to right based on their argument ordering.
FWIW, tar is unique because tar wasn't meant to do archiving to files. If you just did `tar c directory' it would archive the directory to a tape device. The `f' flag is there to redirect the output to a file (instead of the default tape device). So `tar cf foo.tar directory' is not backwards, it just uses an unusual argument convention. The modern form would be `tar --file=foo.tar create directory'.
It's similar to all the file I/O functions that always have the file descriptor first (fprintf etc). These are the heart of Unix. Remember the Unix philosophy: Everything is a file.*
* for a slightly smaller definition of everything than in Plan9
The real/imaginary concept is exactly what I use too. I sort of recall being able to use the real/imaginary concept with other Unix commands as well, but I can't recall which ones off the top of my head.
You can create multiple links with the original names at once with commands like:
ln -s path1/files* path2/
or
ln -s path1/* .
Doing that helped me remember the order because I knew my command could end with a directory as the destination and links would be created there.
Sometimes hardlinks are useful too. You don't always need -s
Edit: Why was this downvoted? I didn't see anyone else mention it until after my post and to me this was an easier way to remember the order than comparing it to "cp".
My god, this thing always keeps biting me. It seems so obvious now with that cp-mnemonic. But it makes me wonder, why does everyone do it wrong in the first place?
My theory is that we're used to see symlinks as part of the "ls -l" output, which lists the link name first, and then the target. Later, we want to create symlinks as we're used to see them (linkname -> target).
The way I remember it is "ln -s target [filename]", where filename is an optional argument to override the default, where the default is a link created in the CWD pointing to target. Easy.
Why don't we have better shells that give hints on these things?
I'm thinking like an IDE will pop up some help text when you begin typing a function name or a recognised special word. Why doesn't the standard sh (bash for me) give me similar help, as I type "ln" it could give me a pop-up with the possible completions and then as I get to "ln -s" it could remind me with "TARGET [NAME] // will create a file named NAME that is a soft link to TARGET, or use TARGET's name if NAME isn't specified". You get the picture.
In a pure text env the help could appear on the next line highlighted appropriately or could be to the right of the cursor or somesuch.
I'm hoping someone will say $CONSOLE does that already ...? Anyone?
It's mostly for historical reasons. More specifically we have restricted shell as text mode only tool, and intellisense-like features/inline help do not tend themselves neatly to line/character based output.
I think that there could be a place for a modern, more graphical orinted command-line interface. In addition to inline help it could display tables more nicely, maybe even allow proportional fonts. And while we are changing stuff, then maybe the object passing idea could be taken from PowerShell.
* The arguments order is just the opposite of common sense. It has taken me years to really remember it, and I still have to think a little every time I use it.
* The default is to create hard link, which you almost never want. And if you do want them, you are probably doing it wrong. Making hard links is just asking for trouble.
I've read that Plan9 has somewhat corrected this whole problem. At least there is no ln command at all. Instead one uses bind, mount, and unmount. Of which bind is most similar to ln -s, but with arguments in reversed order.
The worst part with that kind of mistakes is that you end up never knowing for sure. :)
You start with "ln -s A B" and realize you always make the mistake, so you force yourself to do the opposite of your natural instinct: "ln -s B A". It works until this becomes natural but you still think you always get it wrong, so start doing the opposite of your new natural: "ln -s A B". You'll now be very confused until you force yourself to learn it for good.
This happens to me all the time for various binary things.
I used to get this wrong all the time too. Mentally, I'd be thinking "ln -s source destination", where source was the link and destination was what it pointed to. Of course, that's completely backwards. 'man ln' on OSX didn't help either, since they use the terminology 'source_file [target_file]' which just re-inforced my incorrect thinking (target sounds like something that is pointed to, does it not?).
As other people have mentioned, thinking of it in terms of the files created (ala cp) has helped to learn the correct behavior. I think this is a case where some minor change in the documentation might help to avoid the whole problem.
I think the source of confusion is that linking is closely associated with chains. When you add a link to a chain you always add the new link to the existing chain or
ln -s new_link (onto) existing(chain)
Obviously the target isn't a chain but the association between links and chains is a strong one.
In other words I don't think of creating a link as creating something new _from_ something that already exists, I think of it as adding something new _to_ something that already exists.
As someone who always had that problem, I think it's because I always mentally picture a command as saying "do <action> from <arg0> to <arg1>", ie, "copy this file to that file". But this construct doesn't hold up for linking, so I just have to remember it arbitrarily by remembering cp. function(src, dest) just generally seems to be the unofficial "right way" of ordering things.
My mnemonic for this is to remember that the link name is optional. When you specify only one argument the link name is the base name of the target (in the current working directory). Therefore the link name must be the second argument.
My mneumonic is that in "ln" the "n" comes second, and n is for "name" so the name of the symlink comes second. But I still have to think about it every time...
to your .bashrc? A quick test of this in my terminal and the alias takes precedent over the ln command. Although, I guess it'd be worth doing a few tests to make certain!
when I noticed that I was messing up when using ln, I started thinking this way:
"write what you already know first, so you have time to think about what you'll write next
"what you already know" being the existing file and the second part being the name of the link to the existing file.
It's the same argument order for mv and cp, also the same for rsync and scp
Hell, it's even the same argument order for git-clone.
Pretty much all command lines use "source destination" order.
Why is 'ln' confusing? Because people think of "linking" in a backwards way, it seems that if you're creating a link from A -> B, A is the source and B is the destination. But that's not the meaning of "source destination" that command lines expect
mv B A
A is the new B
cp B A
A is the new B, but B is still there
ln -s B A
A is the new B, except it's just a link, and yes, B is still there.
B is the source, A is the destination. B is the source of the data, A is the destination for that data; the command will create 'A' (or modify it), that's why it's the destination.
For the link itself, B is the destination, but for the operation of creating the link, B is the source, and that's the meaning that's consistent with all other commands.
$cp file_from file_to
and that
$ln -s link_from link_to
has a very similar effect to the cp command above. I haven't messed this up ever since.