how input redirection works?
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
$echo < text_content.txt
$
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
14.04 command-line scripts redirect
add a comment |
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
$echo < text_content.txt
$
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
14.04 command-line scripts redirect
3
echo
does not read from stdin.cat
does. Trycat <text_content.txt
instead.
– John1024
Feb 23 at 7:36
add a comment |
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
$echo < text_content.txt
$
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
14.04 command-line scripts redirect
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
$echo < text_content.txt
$
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
14.04 command-line scripts redirect
14.04 command-line scripts redirect
asked Feb 23 at 7:25
rajini rajarajini raja
235
235
3
echo
does not read from stdin.cat
does. Trycat <text_content.txt
instead.
– John1024
Feb 23 at 7:36
add a comment |
3
echo
does not read from stdin.cat
does. Trycat <text_content.txt
instead.
– John1024
Feb 23 at 7:36
3
3
echo
does not read from stdin. cat
does. Try cat <text_content.txt
instead.– John1024
Feb 23 at 7:36
echo
does not read from stdin. cat
does. Try cat <text_content.txt
instead.– John1024
Feb 23 at 7:36
add a comment |
1 Answer
1
active
oldest
votes
stdin and Commands
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
Effectively, yes. As I've discussed in my answer on What characterizes a file in Linux/Unix?, a file is any object on which you can execute standard operations such as read()
, open()
, write()
, close()
. stdin
being represented via file descriptor 0 is effectively a file in that regard, and any command/process in Linux gets 3 standard file descriptors - stdin,stdout,stderr - when that process is started. What are the actual files behind those file descriptors ? The command doesn't care and shouldn't, as long as it can do operations on it.
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
Now, command is free to do what it will with those file descriptors1. In case of echo
it only deals with stdout
and doesn't perform any action on stdin
at all. So there's nothing wrong with the command itself.
<
redirection will open()
the file text_content.txt
for reading, and it still will assign file descriptor ( for example 3 ) returned from open()
call to file descriptor 0, and if a command is concerned with stdin - it will read from file descriptor 0 as if nothing happened.In fact, you will see that in action, if you run strace -f -e dup2,write,openat bash -c 'echo < text_content.txt
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
dup2(3, 0) = 0
write(1, "n", 1
) = 1
dup2(10, 0) = 0
+++ exited with 0 +++
Notice the dup2()
system call. That's how file descriptor 3 (the file) is assigned/redirected. In sort of cp original copy
syntax, dup2(3,0)
makes a copy of file descriptor 3 to file descriptor 0, and they point to same file.
Notice also that write()
output a newline to file descriptor 1
. That's the default behavior. If we do strace -f -e dup2,write,openat bash -c 'echo FOO < /etc/passwd'
here's what we will see
dup2(3, 0) = 0
write(1, "FOOn", 4FOO
) = 4
dup2(10, 0) = 0
+++ exited with 0 +++
So again, nothing wrong here - redirections are performed properly and echo
does its job of writing stuff to stdout
which is file descriptor 1.
How to actually read a file
Now, lets address something else. How can we read a file in shell ? Well, for that there exists cat
command, which accepts arguments, so you can do just cat file.txt
. Can you do cat < file.txt
? Sure. But that means shell will have to do that dup2()
call, whereas cat file.txt
doesn't - so there's less unnecessary syscalls is what I'm saying.
In complex cases, such as when you need to perform an action on each line of the file, you would do
while IFS= read -r line || [ -n "$line" ]; do
# command to process line variable here
done < /etc/passwd
Now, for the whole loop file descriptor 0
will be a copy of whatever file descriptor is returned from opening /etc/passwd
. Of course, if you can use cat
or another specific command to the job of reading a file - do that. Shell is slow method and has a lot of pitfalls. See also, Why is using a shell loop to process text considered bad practice?
1. Some applications still might care about what they can do with stdin or detect if stdin is a file or pipeline. When stdin
file descriptor is assigned as read-end of pipeline (which is also a file descriptor) the output is not seekable (meaning that application written in C or another language cannot use seek()
syscall to quickly navigate to specific byte offset in a file). A good example of that is given in the question titled What is the difference between “cat file | ./binary” and “./binary < file”?
Sidenote: on Linux it's not exactly keyboard from where stdin gets its input. If you do
$ ls -l /proc/self/fd/0
lrwx------ 1 serg serg 64 Feb 23 16:45 /proc/self/fd/0 -> /dev/pts/0
you will see in the output that it is /dev/pts/0
terminal device to which stdin
points initially. The terminal device then interfaces with keyboard, or it could as well be serial cable.
Additionally, if file is not very large, you could take advantage of bash
's mapfile
builtin to read lines into array:
mapfile -t < /etc/passwd
for i in "${MAPFILE[@]}"; do echo "$i"; done
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "89"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1120556%2fhow-input-redirection-works%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
stdin and Commands
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
Effectively, yes. As I've discussed in my answer on What characterizes a file in Linux/Unix?, a file is any object on which you can execute standard operations such as read()
, open()
, write()
, close()
. stdin
being represented via file descriptor 0 is effectively a file in that regard, and any command/process in Linux gets 3 standard file descriptors - stdin,stdout,stderr - when that process is started. What are the actual files behind those file descriptors ? The command doesn't care and shouldn't, as long as it can do operations on it.
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
Now, command is free to do what it will with those file descriptors1. In case of echo
it only deals with stdout
and doesn't perform any action on stdin
at all. So there's nothing wrong with the command itself.
<
redirection will open()
the file text_content.txt
for reading, and it still will assign file descriptor ( for example 3 ) returned from open()
call to file descriptor 0, and if a command is concerned with stdin - it will read from file descriptor 0 as if nothing happened.In fact, you will see that in action, if you run strace -f -e dup2,write,openat bash -c 'echo < text_content.txt
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
dup2(3, 0) = 0
write(1, "n", 1
) = 1
dup2(10, 0) = 0
+++ exited with 0 +++
Notice the dup2()
system call. That's how file descriptor 3 (the file) is assigned/redirected. In sort of cp original copy
syntax, dup2(3,0)
makes a copy of file descriptor 3 to file descriptor 0, and they point to same file.
Notice also that write()
output a newline to file descriptor 1
. That's the default behavior. If we do strace -f -e dup2,write,openat bash -c 'echo FOO < /etc/passwd'
here's what we will see
dup2(3, 0) = 0
write(1, "FOOn", 4FOO
) = 4
dup2(10, 0) = 0
+++ exited with 0 +++
So again, nothing wrong here - redirections are performed properly and echo
does its job of writing stuff to stdout
which is file descriptor 1.
How to actually read a file
Now, lets address something else. How can we read a file in shell ? Well, for that there exists cat
command, which accepts arguments, so you can do just cat file.txt
. Can you do cat < file.txt
? Sure. But that means shell will have to do that dup2()
call, whereas cat file.txt
doesn't - so there's less unnecessary syscalls is what I'm saying.
In complex cases, such as when you need to perform an action on each line of the file, you would do
while IFS= read -r line || [ -n "$line" ]; do
# command to process line variable here
done < /etc/passwd
Now, for the whole loop file descriptor 0
will be a copy of whatever file descriptor is returned from opening /etc/passwd
. Of course, if you can use cat
or another specific command to the job of reading a file - do that. Shell is slow method and has a lot of pitfalls. See also, Why is using a shell loop to process text considered bad practice?
1. Some applications still might care about what they can do with stdin or detect if stdin is a file or pipeline. When stdin
file descriptor is assigned as read-end of pipeline (which is also a file descriptor) the output is not seekable (meaning that application written in C or another language cannot use seek()
syscall to quickly navigate to specific byte offset in a file). A good example of that is given in the question titled What is the difference between “cat file | ./binary” and “./binary < file”?
Sidenote: on Linux it's not exactly keyboard from where stdin gets its input. If you do
$ ls -l /proc/self/fd/0
lrwx------ 1 serg serg 64 Feb 23 16:45 /proc/self/fd/0 -> /dev/pts/0
you will see in the output that it is /dev/pts/0
terminal device to which stdin
points initially. The terminal device then interfaces with keyboard, or it could as well be serial cable.
Additionally, if file is not very large, you could take advantage of bash
's mapfile
builtin to read lines into array:
mapfile -t < /etc/passwd
for i in "${MAPFILE[@]}"; do echo "$i"; done
add a comment |
stdin and Commands
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
Effectively, yes. As I've discussed in my answer on What characterizes a file in Linux/Unix?, a file is any object on which you can execute standard operations such as read()
, open()
, write()
, close()
. stdin
being represented via file descriptor 0 is effectively a file in that regard, and any command/process in Linux gets 3 standard file descriptors - stdin,stdout,stderr - when that process is started. What are the actual files behind those file descriptors ? The command doesn't care and shouldn't, as long as it can do operations on it.
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
Now, command is free to do what it will with those file descriptors1. In case of echo
it only deals with stdout
and doesn't perform any action on stdin
at all. So there's nothing wrong with the command itself.
<
redirection will open()
the file text_content.txt
for reading, and it still will assign file descriptor ( for example 3 ) returned from open()
call to file descriptor 0, and if a command is concerned with stdin - it will read from file descriptor 0 as if nothing happened.In fact, you will see that in action, if you run strace -f -e dup2,write,openat bash -c 'echo < text_content.txt
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
dup2(3, 0) = 0
write(1, "n", 1
) = 1
dup2(10, 0) = 0
+++ exited with 0 +++
Notice the dup2()
system call. That's how file descriptor 3 (the file) is assigned/redirected. In sort of cp original copy
syntax, dup2(3,0)
makes a copy of file descriptor 3 to file descriptor 0, and they point to same file.
Notice also that write()
output a newline to file descriptor 1
. That's the default behavior. If we do strace -f -e dup2,write,openat bash -c 'echo FOO < /etc/passwd'
here's what we will see
dup2(3, 0) = 0
write(1, "FOOn", 4FOO
) = 4
dup2(10, 0) = 0
+++ exited with 0 +++
So again, nothing wrong here - redirections are performed properly and echo
does its job of writing stuff to stdout
which is file descriptor 1.
How to actually read a file
Now, lets address something else. How can we read a file in shell ? Well, for that there exists cat
command, which accepts arguments, so you can do just cat file.txt
. Can you do cat < file.txt
? Sure. But that means shell will have to do that dup2()
call, whereas cat file.txt
doesn't - so there's less unnecessary syscalls is what I'm saying.
In complex cases, such as when you need to perform an action on each line of the file, you would do
while IFS= read -r line || [ -n "$line" ]; do
# command to process line variable here
done < /etc/passwd
Now, for the whole loop file descriptor 0
will be a copy of whatever file descriptor is returned from opening /etc/passwd
. Of course, if you can use cat
or another specific command to the job of reading a file - do that. Shell is slow method and has a lot of pitfalls. See also, Why is using a shell loop to process text considered bad practice?
1. Some applications still might care about what they can do with stdin or detect if stdin is a file or pipeline. When stdin
file descriptor is assigned as read-end of pipeline (which is also a file descriptor) the output is not seekable (meaning that application written in C or another language cannot use seek()
syscall to quickly navigate to specific byte offset in a file). A good example of that is given in the question titled What is the difference between “cat file | ./binary” and “./binary < file”?
Sidenote: on Linux it's not exactly keyboard from where stdin gets its input. If you do
$ ls -l /proc/self/fd/0
lrwx------ 1 serg serg 64 Feb 23 16:45 /proc/self/fd/0 -> /dev/pts/0
you will see in the output that it is /dev/pts/0
terminal device to which stdin
points initially. The terminal device then interfaces with keyboard, or it could as well be serial cable.
Additionally, if file is not very large, you could take advantage of bash
's mapfile
builtin to read lines into array:
mapfile -t < /etc/passwd
for i in "${MAPFILE[@]}"; do echo "$i"; done
add a comment |
stdin and Commands
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
Effectively, yes. As I've discussed in my answer on What characterizes a file in Linux/Unix?, a file is any object on which you can execute standard operations such as read()
, open()
, write()
, close()
. stdin
being represented via file descriptor 0 is effectively a file in that regard, and any command/process in Linux gets 3 standard file descriptors - stdin,stdout,stderr - when that process is started. What are the actual files behind those file descriptors ? The command doesn't care and shouldn't, as long as it can do operations on it.
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
Now, command is free to do what it will with those file descriptors1. In case of echo
it only deals with stdout
and doesn't perform any action on stdin
at all. So there's nothing wrong with the command itself.
<
redirection will open()
the file text_content.txt
for reading, and it still will assign file descriptor ( for example 3 ) returned from open()
call to file descriptor 0, and if a command is concerned with stdin - it will read from file descriptor 0 as if nothing happened.In fact, you will see that in action, if you run strace -f -e dup2,write,openat bash -c 'echo < text_content.txt
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
dup2(3, 0) = 0
write(1, "n", 1
) = 1
dup2(10, 0) = 0
+++ exited with 0 +++
Notice the dup2()
system call. That's how file descriptor 3 (the file) is assigned/redirected. In sort of cp original copy
syntax, dup2(3,0)
makes a copy of file descriptor 3 to file descriptor 0, and they point to same file.
Notice also that write()
output a newline to file descriptor 1
. That's the default behavior. If we do strace -f -e dup2,write,openat bash -c 'echo FOO < /etc/passwd'
here's what we will see
dup2(3, 0) = 0
write(1, "FOOn", 4FOO
) = 4
dup2(10, 0) = 0
+++ exited with 0 +++
So again, nothing wrong here - redirections are performed properly and echo
does its job of writing stuff to stdout
which is file descriptor 1.
How to actually read a file
Now, lets address something else. How can we read a file in shell ? Well, for that there exists cat
command, which accepts arguments, so you can do just cat file.txt
. Can you do cat < file.txt
? Sure. But that means shell will have to do that dup2()
call, whereas cat file.txt
doesn't - so there's less unnecessary syscalls is what I'm saying.
In complex cases, such as when you need to perform an action on each line of the file, you would do
while IFS= read -r line || [ -n "$line" ]; do
# command to process line variable here
done < /etc/passwd
Now, for the whole loop file descriptor 0
will be a copy of whatever file descriptor is returned from opening /etc/passwd
. Of course, if you can use cat
or another specific command to the job of reading a file - do that. Shell is slow method and has a lot of pitfalls. See also, Why is using a shell loop to process text considered bad practice?
1. Some applications still might care about what they can do with stdin or detect if stdin is a file or pipeline. When stdin
file descriptor is assigned as read-end of pipeline (which is also a file descriptor) the output is not seekable (meaning that application written in C or another language cannot use seek()
syscall to quickly navigate to specific byte offset in a file). A good example of that is given in the question titled What is the difference between “cat file | ./binary” and “./binary < file”?
Sidenote: on Linux it's not exactly keyboard from where stdin gets its input. If you do
$ ls -l /proc/self/fd/0
lrwx------ 1 serg serg 64 Feb 23 16:45 /proc/self/fd/0 -> /dev/pts/0
you will see in the output that it is /dev/pts/0
terminal device to which stdin
points initially. The terminal device then interfaces with keyboard, or it could as well be serial cable.
Additionally, if file is not very large, you could take advantage of bash
's mapfile
builtin to read lines into array:
mapfile -t < /etc/passwd
for i in "${MAPFILE[@]}"; do echo "$i"; done
stdin and Commands
On my understanding, any command that reads from standard input (i.e keyboard), that it gets its input from a file.
Effectively, yes. As I've discussed in my answer on What characterizes a file in Linux/Unix?, a file is any object on which you can execute standard operations such as read()
, open()
, write()
, close()
. stdin
being represented via file descriptor 0 is effectively a file in that regard, and any command/process in Linux gets 3 standard file descriptors - stdin,stdout,stderr - when that process is started. What are the actual files behind those file descriptors ? The command doesn't care and shouldn't, as long as it can do operations on it.
But echo command does not read and display the text_content.txt on the terminal. what's wrong here?
Now, command is free to do what it will with those file descriptors1. In case of echo
it only deals with stdout
and doesn't perform any action on stdin
at all. So there's nothing wrong with the command itself.
<
redirection will open()
the file text_content.txt
for reading, and it still will assign file descriptor ( for example 3 ) returned from open()
call to file descriptor 0, and if a command is concerned with stdin - it will read from file descriptor 0 as if nothing happened.In fact, you will see that in action, if you run strace -f -e dup2,write,openat bash -c 'echo < text_content.txt
openat(AT_FDCWD, "/etc/passwd", O_RDONLY) = 3
dup2(3, 0) = 0
write(1, "n", 1
) = 1
dup2(10, 0) = 0
+++ exited with 0 +++
Notice the dup2()
system call. That's how file descriptor 3 (the file) is assigned/redirected. In sort of cp original copy
syntax, dup2(3,0)
makes a copy of file descriptor 3 to file descriptor 0, and they point to same file.
Notice also that write()
output a newline to file descriptor 1
. That's the default behavior. If we do strace -f -e dup2,write,openat bash -c 'echo FOO < /etc/passwd'
here's what we will see
dup2(3, 0) = 0
write(1, "FOOn", 4FOO
) = 4
dup2(10, 0) = 0
+++ exited with 0 +++
So again, nothing wrong here - redirections are performed properly and echo
does its job of writing stuff to stdout
which is file descriptor 1.
How to actually read a file
Now, lets address something else. How can we read a file in shell ? Well, for that there exists cat
command, which accepts arguments, so you can do just cat file.txt
. Can you do cat < file.txt
? Sure. But that means shell will have to do that dup2()
call, whereas cat file.txt
doesn't - so there's less unnecessary syscalls is what I'm saying.
In complex cases, such as when you need to perform an action on each line of the file, you would do
while IFS= read -r line || [ -n "$line" ]; do
# command to process line variable here
done < /etc/passwd
Now, for the whole loop file descriptor 0
will be a copy of whatever file descriptor is returned from opening /etc/passwd
. Of course, if you can use cat
or another specific command to the job of reading a file - do that. Shell is slow method and has a lot of pitfalls. See also, Why is using a shell loop to process text considered bad practice?
1. Some applications still might care about what they can do with stdin or detect if stdin is a file or pipeline. When stdin
file descriptor is assigned as read-end of pipeline (which is also a file descriptor) the output is not seekable (meaning that application written in C or another language cannot use seek()
syscall to quickly navigate to specific byte offset in a file). A good example of that is given in the question titled What is the difference between “cat file | ./binary” and “./binary < file”?
Sidenote: on Linux it's not exactly keyboard from where stdin gets its input. If you do
$ ls -l /proc/self/fd/0
lrwx------ 1 serg serg 64 Feb 23 16:45 /proc/self/fd/0 -> /dev/pts/0
you will see in the output that it is /dev/pts/0
terminal device to which stdin
points initially. The terminal device then interfaces with keyboard, or it could as well be serial cable.
Additionally, if file is not very large, you could take advantage of bash
's mapfile
builtin to read lines into array:
mapfile -t < /etc/passwd
for i in "${MAPFILE[@]}"; do echo "$i"; done
edited Feb 23 at 9:24
answered Feb 23 at 8:13
Sergiy KolodyazhnyySergiy Kolodyazhnyy
73.4k9153318
73.4k9153318
add a comment |
add a comment |
Thanks for contributing an answer to Ask Ubuntu!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2faskubuntu.com%2fquestions%2f1120556%2fhow-input-redirection-works%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
echo
does not read from stdin.cat
does. Trycat <text_content.txt
instead.– John1024
Feb 23 at 7:36