What does " 2>&1 " mean?

stackoverflow.com

381 points by alexmolas 21 hours ago


wahern - 19 hours ago

I find it easier to understand in terms of the Unix syscall API. `2>&1` literally translates as `dup2(1, 2)`, and indeed that's exactly how it works. In the classic unix shells that's all that happens; in more modern shells there may be some additional internal bookkeeping to remember state. Understanding it as dup2 means it's easier to understand how successive redirections work, though you also have to know that redirection operators are executed left-to-right, and traditionally each operator was executed immediately as it was parsed, left-to-right. The pipe operator works similarly, though it's a combination of fork and dup'ing, with the command being forked off from the shell as a child before processing the remainder of the line.

Though, understanding it this way makes the direction of the angled bracket a little odd; at least for me it's more natural to understand dup2(2, 1) as 2<1, as in make fd 2 a duplicate of fd 1, but in terms of abstract I/O semantics that would be misleading.

ptaffs - 15 minutes ago

I understood the point of the question was how shells work seems very context driven. An & here means something different to an & there. IFS=\| read A B C <<< "first|second|third" the read is executed and the IFS assignment is local to the one command echo hello this will "hello this", even though in the assignment above the space was important an & at the end of a line is run the task background and in the middle of the redirect isn't. All these things can be learned, but it's hard to explain the patterns, I think.

ontouchstart - 3 hours ago

Sometime all you need is to RTMF from the source instead of Nth hand information (N > 1)

https://www.gnu.org/software/bash/manual/html_node/Redirecti...

raincole - 15 hours ago

The comments on stackoverflow say the words out of my mouth so I'll just copy & paste here:

> but then shouldn't it rather be &2>&1?

> & is only interpreted to mean "file descriptor" in the context of redirections. Writing command &2>& is parsed as command & and 2>&1

That's where all the confusion comes from. I believe most people can intuitively understand > is redirection, but the asymmetrical use of & throws them off.

Interestingly, Powershell also uses 2>&1. Given an once-a-lifetime chance to redesign shell, out of all the Unix relics, they chose to keep (borrow) this.

james_marks - 3 hours ago

Claude’s answer, which is the only one that clicked for me:

Normally when you do something like command > file.txt, you’re only capturing the normal output — errors still go to your screen.

2>&1 is how you say: “send the error pipe into the same place as the normal output pipe.” Breaking it down without jargon: • 2 means “the error output” • > means “send it to” • &1 means “wherever the normal output is currently going” (the & just means “I’m referring to a pipe, not a file named 1”)

solomonb - 17 hours ago

Man I miss stack overflow. It feels so much better to ask humans a question then the machine, but it feels impossible to put the lid back on the box.

amelius - 18 hours ago

It's a reminder of how archaic the systems we use are.

File descriptors are like handing pointers to the users of your software. At least allow us to use names instead of numbers.

And sh/bash's syntax is so weird because the programmer at the time thought it was convenient to do it like that. Nobody ever asked a user.

arjie - 18 hours ago

Redirects are fun but there are way more than I actually routinely use. One thing I do is the file redirects.

    diff <(seq 1 20) <(seq 1 10)
I do that with diff <(xxd -r file.bin) <(xxd -r otherfile.bin) sometimes when I should expect things to line up and want to see where things break.
gnabgib - 19 hours ago

Better: Understanding Linux's File Descriptors: A Deep Dive Into '2>&1' and Redirection https://news.ycombinator.com/item?id=41384919 https://news.ycombinator.com/item?id=39095755

lgeorget - 5 hours ago

It reminds me of this answer I made some years ago: https://unix.stackexchange.com/a/138046

The question was how to remember it's "2>&1" and not "2&>1". If you think of "&1" as the address/destination of, the syntax is quite natural.

MathMonkeyMan - 14 hours ago

I regularly refer to [the unix shell specification][1] to remember the specifics of ${foo%%bar} versus ${foo#bar}, ${parameter:+word} versus ${parameter:-word}, and so on.

It also teaches how && and || work, their relation to [output redirection][3] and [command piping][2], [(...) versus {...}][4], and tricky parts like [word expansion][5], even a full grammar. It's not exciting reading, but it's mostly all there, and works on all POSIXy shells, e.g. sh, bash, ksh, dash, ash, zsh.

[1]: https://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html

[2]: https://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html...

[3]: https://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html...

[4]: https://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html...

[5]: https://pubs.opengroup.org/onlinepubs/7908799/xcu/chap2.html...

csours - 18 hours ago

If you need to know what 2>&1 means, then I would recommend shellcheck

It's very, very easy to get shell scripts wrong; for instance the location of the file redirect operator in a pipeline is easy to get wrong.

vessenes - 19 hours ago

Not sure why this link and/or question is here, except to say LLMs like this incantation.

It redirects STDERR (2) to where STDOUT is piped already (&1). Good for dealing with random CLI tools if you're not a human.

k3vinw - 4 hours ago

Perhaps it’s the odd placement of the ampersand. Something like >2&1 would make more sense to me.

On the other hand, pipe “|” is brilliant!

ucarion - 18 hours ago

I've almost never needed any of these, but there's all sorts of weird redirections you can do in GNU Bash: https://www.gnu.org/software/bash/manual/bash.html#Redirecti...

xg15 - 9 hours ago

Always wondered how the parser managed the ambiguity between & for file descriptors and & to start background tasks. (And without a good mental model, I kept forgetting where to put the & correctly in redirects)

Treating ">&" as a distinct operator actually makes an elegant solution here. I like the idea.

kazinator - 18 hours ago

It means redirect file descriptor 2 to the same destination as file descriptor 1.

Which actually means that an undelrying dup2 operation happens in this direction:

   2 <- 1   // dup2(2, 1)
The file description at [1] is duplicated into [2], thereby [2] points to the same object. Anything written to stderr goes to the same device that stdout is sending to.

The notation follows I/O redirections: cmd > file actually means that a descriptor [n] is first created for the open file, and then that descriptor's decription is duplicated into [1]:

   n <- open("file", O_RDONLY)
   1 <- n
Normal_gaussian - 17 hours ago

I know the underlying call, but I always see the redirect symbols as indicating that "everything" on the big side of the operator fits into a small bit of what is on the small side of the operator. Like a funnel for data. I don't know the origin, but I'm believing my fiction is right regardless. It makes <(...) make intuitive sense.

The comment about "why not &2>&1" is probably the best one on the page, with the answer essentially being that it would complicate the parser too much / add an unnecessary byte to scripts.

wodenokoto - 18 hours ago

I enjoyed the commenter asking “Why did they pick such arcane stuff as this?” - I don’t think I touch more arcane stuff than shell, so asking why shell used something that is arcane relative to itself is to me arcane squared.

kalterdev - 10 hours ago

rc [1] replaced it with a far more telling >[1=2] and >[1=] for closing.

1: https://p9f.org/sys/doc/rc.html

charcircuit - 15 hours ago

I am surprised that there still is no built in way to pipe stdout and stderr. *| would be much more ergonomic than 2>&1 |.

emmelaich - 18 hours ago

A gotcha for me originally and perhaps others is that while using ordering like

   $ ./outerr  >blah 2>&1
sends stdout and stderr to blah, imitating the order with pipe instead does not.

   $ ./outerr  | 2>&1 cat >blah
   err
This is because | is not a mere redirector but a statement terminator.

    (where outerr is the following...)
    echo out 
    echo err >&2
maxeda - 18 hours ago

> I am thinking that they are using & like it is used in c style programming languages. As a pointer address-of operator. [...] 2>&1 would represent 'direct file 2 to the address of file 1'.

I had never made the connection of the & symbol in this context. I think I never really understood the operation before, treating it just as a magic incantation but reading this just made it click for me.

nikeee - 17 hours ago

So if i happen to know the numbers of other file descriptors of the process (listed in /proc), i can redirect to other files opened in the current process? 2>&1234? Or is it restricted to 0/1/2 by the shell?

Would probably be hard to guess since the process may not have opened any file once it started.

zem - 19 hours ago

back when stackoverflow was still good and useful, I asked about some stderr manipulation[0] and learnt a lot from the replies

[0] https://stackoverflow.com/questions/3618078/pipe-only-stderr...

nurettin - 18 hours ago

I saw this newer bash syntax for redirecting all output some years ago on irc

    foo &> file  
    foo |& program
adzm - 19 hours ago

I always wondered if there ever was a standard stream for stdlog which seems useful, and comes up in various places but usually just as an alias to stderr

AnimalMuppet - 15 hours ago

Somewhat off topic, but related: I worked at this place that made internet security software. It ran on Windows, and on various flavors of Unix.

One customer complained about our software corrupting files on their hard disk. Turns out they had modified their systems so that a newly-spawned program was not given a stderr. That is, it was not handed 0, 1, and 2 (file descriptors), but only 0 and 1. So whenever our program wrote something to stderr, it wrote to whatever file had been the first one opened by the program.

We talked about fixing this, briefly. Instead we decided to tell the customer to fix their broken environment.

otikik - 10 hours ago

To me it means “I didn’t want to come up with an intelligible syntax for this”. Shell scripts have many dark corners and sharp edges like this is one.

everyone - 4 hours ago

stackoverflow, how quaint. Anyone here remember when it was actually useful and questions like the one featured could be asked and answered?

tempodox - 12 hours ago

That’s nothing, try `&>`.

whatever1 - 15 hours ago

Awesome. Next week I will forget it again.

kuon - 7 hours ago

It was never fully clear to me why the ordre mattered.

hinkley - 9 hours ago

I first encountered this thirty four years ago and I still hate it. Almost as much as I hate when people ask me to explain it.

Look man, I didn’t invent this stupid shit, and I’m not telling you it’s brilliant, so don’t kill the messenger.

I thought I’d seen somewhere that zsh had a better way to do this but I must have imagined it. Or maybe I’m confusing it with fish.

JackAcid - 16 hours ago

A.I. has made the self-important neckbeards of Stack Overflow obsolete.

nodesocket - 17 hours ago

I understand how this works, but wouldn’t a more clear syntax be:

command &2>&1

Since the use of & signifies a file descriptor. I get what this ACTUALLY does is run command in the background and then run 2 sending its stout to stdout. That’s completely not obvious by the way.

aichen_dev - 6 hours ago

[dead]

datawars - 5 hours ago

[dead]

esafak - 16 hours ago

It means someone did not bother to name their variables properly, reminding you to use a shell from this century.