Difference between redirection position in messages "echo" and "2", "echo message" and "2" and "> and 2 echo messages"
I came across a different location for the redirect symbol ( >
, <
). For example:
echo>&2 message
message
echo message >&2
message
>&2 echo message
message
For all forms I got the same result. I used file redirection ( >filename
) instead of stream redirection ( >&2
). Also I used input redirection ( <filename
). The result is the same in bash and windows cmd.
Is there a difference in the location of the redirect?
PS I've only seen the "echo message> & 2" form in the books.
source to share
Redirecting the flow X>&Y
in the shell uses a system call dup2(2)
to replace one file descriptor associated with the flow ( stdin
, stdout
, stderr
or something else) with the other.
Basically, it 2>&1
literally dup2(2, 1)
means "to attach FD 2 to what is currently connected to FD 1, possibly by closing FD 2 first".
This has two essential properties:
-
For this to work, the file descriptor to replace the existing one with must already represent the file / device we want to bind our descriptor to.
-
As soon as we replaced one file descriptor with another and then reopened that file descriptor used as a replacement for some other file / device, both file descriptors are disabled. Hence, order matters:
foo >/dev/null 2>&1
ok because he's mostly
// 1) do >/dev/null close(1); fd = open("/dev/null", O_WRONLY, 0666); // fd will be == 1 on success. // 2) do 2>&1 dup2(2, 1);
so that FDs 2 and 1 are open in the same file "/ dev / null", while
foo 2>&1 >/dev/null
will first attach fd 2 to the same file that fd 1 is attached to, and then immediately bind fd 1 to the new file -
/dev/null
- leaving fd 2 still open for whatever fd 1 is attached to during the first redirect:// 1) do 2>&1 dup2(2, 1); // 2) do >/dev/null close(1); // FD 2 is still open to the same file FD 1 was just before closing. fd = open("/dev/null", O_WRONLY, 0666); // fd will be == 1 on success // Now both FDs are opened to different files.
source to share
have a look at the bash guide , especially the file descriptor section. commands redirect standard input to standard error. if you filter 2>/dev/null
, you should see the messages disappear. hope this helps.
source to share
For simple commands
echo >&2 message
- the only one that differs, and it differs only in that it is incompatible with the POSIX sh specification; support for redirection at any position - bash extension.
>&2 echo message
and are echo message >&2
exactly the same, and support for both is guaranteed in the POSIX sh standard.
For compound commands
Redirects are only valid at the end of compound commands. I.e:
while read -r line; do printf '%s\n' "$line"; done <file
... is valid but
<file while read -r line; do printf '%s\n' "$line"; done
... POSIX support is not guaranteed.
Positions within a compound command will apply to individual subcommands, so a bash extension that allows redirects to any position within a command is meaningless here.
Formal grammar
The following is a quote from the POSIX shell grammar specification:
cmd_prefix : io_redirect
| cmd_prefix io_redirect
| ASSIGNMENT_WORD
| cmd_prefix ASSIGNMENT_WORD
;
cmd_suffix : io_redirect
| cmd_suffix io_redirect
| WORD
| cmd_suffix WORD
;
simple_command : cmd_prefix cmd_word cmd_suffix
| cmd_prefix cmd_word
| cmd_prefix
| cmd_name cmd_suffix
| cmd_name
;
command : simple_command
| compound_command
| compound_command redirect_list
| function_definition
redirect_list : io_redirect
| redirect_list io_redirect
;
Thus, in a shell that implements POSIX sh without extensions:
- Permissions are allowed within
cmd_prefix
or << 27>, i.e. at the beginning or end of a simple command - Redistribution is allowed at the end (only) of a compound command.
source to share