126 comments

[ 3.7 ms ] story [ 193 ms ] thread
I used to have this problem. Then I realized that if I want to really copy a file, I type

$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.

I used to have this problem too, and then I read the linked article and now remember the relationship between ln and cp and never got it wrong since.

Also I wonder how many people can say the same thing as the article and still get upvoted.

I said it in fewer words and didn't add any adsense junk.
It's so similar to cp that GNU cp has

  cp -l from to
Good, but cp -l is for hard links and cp -s is for symlinks. Most of the time people want the latter.
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)

"to" is an entity that doesn't exist yet.
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.

And people say Linux isn't user-friendly! :)

In my experience the more variable argument often comes last, presumably for easy reuse. For example...

  $chown user1 file1
  $chown user1 file2

  $ln -s file1 file2
  $ln -s file1 file3
...seems more likely than...

  $chown user1 file1
  $chown user2 file1

  $ln -s file1 file2
  $ln -s file3 file2
That's the reason behind a most of the argument orders in the Haskell standard library: To ease Currying.
Why did you do that? Now I really want to implement a const and flip for text arguments :)
That could be a nice command line tool. Please include a Data.Function.on, and find a way to make it useful.

flip would actually be quite useful for me on grep. I often search the some corpus of text, but change the pattern.

This happens to be the first comment in the thread on Reddit.
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.

That's what I would have intuitively thought. But I swear it worked the other way sometimes!
This phrasing confused me more.

`$ 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:

<a href="http://google.com/>Google</a>;

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.
I say in my head "link symboliicaly from HERE to THERE"

It took me a long time till I realized that saying it thus made me always recall it properly.

Less ambiguously:

  cp    existing_thing new_thing
  ln -s existing_thing new_thing
That's exactly how I remember it too

  ln -s 'the one that exists' 'the one that doesnt exist'
I actually say that to myself as I'm typing the command. Since I started doing that, I've never gotten it wrong.
Not the most helpful of advice for those that can't remember which way round the cp command takes its arguments either...
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
That's funny, I do too. I always thought it was just me...
It is never just you. An important lesson I learned while programming.
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.
Yeah it seems backwards to me as well. I always thought it was the only one.
The annoying thing is that the mklink command in Windows uses the opposite order, so you have to do

mklink link_to link_from

EDIT: formatting.

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?
At least for me, it's because I say in my head "link $FOO to $BAR", which must be typed "ln -s $BAR $FOO".
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 problem is that you're using the wrong definition of "link". I also say "link $foo to $bar", but that puts it in the right order:

I have a folder. I want to link that folder to some other name, over yonder. " ln -s foo bar". See?

"I want to make a symbolic <link> to this <source>"

"I want to copy this <source> to this <destination>"

vs.

"I want this <source> to be accessible via this <link>"

Because in the final result, the link points to the original. The directory listing will even say

    link -> original
So naturally you want to say that in the command, "make a link that points to the original".

I had a friend who gave up and made an alias that sorted out which of the arguments existed and did The Right Thing.

Ditto. I just remember that it's the reverse of tar, but the cp trick is better.
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.
I suspect strcat and strcpy were parameterized as such to match memcpy.

Why memcpy was parameterized in that order, I am not certain.

memcpy(lvalue, rvalue, size)

lvalue == write location rvalue == read location

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'.

Probably in order to be consistent with assignment.
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'.

Indeed. Assignment should really look like something like this this:

  expression -> variable;
Forth uses

  expression memory-location !
to store and

  memory-location @
to read.
I think it's more to do with the requirement that mandatory arguments have to go before optional ones (it wouldn't work the other way round).
In strcpy, memcpy and partners, both arguments are (rather obviously) mandatory...
Possibly for consistency with functions that take varargs, e.g. sprintf
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

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?

Except volume dials.
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.
And gas valves.
I conclude from this, by process of logical inference, that "louder" must be a type of "tighter".

"Forward" is also "tighter", apparently.

tar is like that because of command lines

tar [args] [one thing] [list of things]

it'd be wierd if it was

tar [args] [list of things] [filename]

... but i will admit i frequently make that mistake.

But, as a counterpoint, if you want to copy several things to a folder, you do:

  cp [args] [list of things] [destination folder]
But you can also do

  cp [args] -t [destination folder] [list of things]
The same is true of mv. This is useful if you are piping filenames to xargs.
Thanks! I always wondered what was the purpose of -t. Never occurred to me it was to allow you to reverse the order of args.
tar is actually

  tar [args] [list of things]
where [args] may contain [-f filename], among other things.

That is, the destination filename is an optional argument; by default tar outputs to a tape device or stdout, depending on the implementation.

At least in GNU tar, the target filename can very well be specified as the last argument:

  tar -c foo.txt bar.txt baz.txt -f stuff.tar
I don't feel it's a crime. For that matter, I don't even prefer one over the other.

For "mv A B"

I've no problem saying either

  mv into A the contents of B
or

  mv the contents of A into B
Who does prefer one over the other? The lack of consistency is the real problem.
My first car (a 1967 Dodge Monaco) had 'backwards' lug nuts on the left hand side of the car...

http://en.wikipedia.org/wiki/Lug_nut#History

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.

Nah. I used to change tyres for a living and I never came across a car with backwards nuts on either side.
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.
Most assemblers have fx

  mov a,b
as from b to a.
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'.
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.

I always think that you get strcpy by first writing

   *target = source*
Step two is realizing that things don't work that way in C. Step three is sprinkling in semantic sugar to make it work.

strcat, then, is for symmetry with strcpy.

a copy points to the original (for an instant anyway) the same way that a link points to the original:

  cp original copy

  ln -s original link
I've always used complex numbers as a mnemonic: real + imaginary, a + bi (obviously the file is real and the softlink is "imaginary").

http://en.wikipedia.org/wiki/Complex_number

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.
rm only has the real component before you issue it and the imaginary one afterwards ;)
Its like a black hole in my mind. Every single time I screw this up. I've.... just had to learn to live with deleting my first crappy link. :)
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...
A co-worker once told me to remember it like: "I have a (src) that I'd like to call (dst)"
Funny, I have a similar problem with scp.
If you leave off the second argument, you don't need to remember it. Much easier.
That's how I finally got it right. Now I just remember that the second arg ("dest") is optional.
I just read the -s as "source" even though it really means symbolic.

ln -s source fakename

(comment deleted)
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".

I think up to the 100th time reading the man page I would forget, until I memorized the following mantra:

    ln -s target link_name
Same here, I just memorized "target [the] link name".
I also occasionally forget the -s, and really wish it was the default since I'm almost always creating a symbolic link.
Could you maybe add:

alias ln='ln -s'

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!

Sure, but I'd rather not get bitten when I'm on a system where I don't have that alias defined.
Someone told me 'fact before fiction' a long time ago, and I've never forgotten it.
My mneumonic is "lentil", since it's ln (-s) <T-for-target> <L-for-link>.
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.
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.

(comment deleted)