Echo to file descriptor overwrites the file?
I am having trouble understanding what is happening when I try to write to a file descriptor? It appears to be overwriting the original contents? Is this expected behaviour?
I have replicated this in the example below:
$ echo "The quick brown fox ..." > example.txt
$ echo "The quick brown fox ..." >> example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ exec 88<>example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
ck brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
jumped
n fox ...
The quick brown fox ...
bash files exec
New contributor
add a comment |
I am having trouble understanding what is happening when I try to write to a file descriptor? It appears to be overwriting the original contents? Is this expected behaviour?
I have replicated this in the example below:
$ echo "The quick brown fox ..." > example.txt
$ echo "The quick brown fox ..." >> example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ exec 88<>example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
ck brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
jumped
n fox ...
The quick brown fox ...
bash files exec
New contributor
add a comment |
I am having trouble understanding what is happening when I try to write to a file descriptor? It appears to be overwriting the original contents? Is this expected behaviour?
I have replicated this in the example below:
$ echo "The quick brown fox ..." > example.txt
$ echo "The quick brown fox ..." >> example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ exec 88<>example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
ck brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
jumped
n fox ...
The quick brown fox ...
bash files exec
New contributor
I am having trouble understanding what is happening when I try to write to a file descriptor? It appears to be overwriting the original contents? Is this expected behaviour?
I have replicated this in the example below:
$ echo "The quick brown fox ..." > example.txt
$ echo "The quick brown fox ..." >> example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ exec 88<>example.txt
$ cat example.txt
The quick brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
ck brown fox ...
The quick brown fox ...
$ echo "jumped" >&88
$ cat example.txt
jumped
jumped
n fox ...
The quick brown fox ...
bash files exec
bash files exec
New contributor
New contributor
edited 17 hours ago
Community♦
1
1
New contributor
asked 19 hours ago
ZoonoseZoonose
333
333
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
@Zoonose: When you executecat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you executeexec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.
– P Daddy
16 hours ago
2
Even if youcat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the>>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.
– ilkkachu
10 hours ago
add a comment |
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.
New contributor
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
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: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
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
});
}
});
Zoonose is a new contributor. Be nice, and check out our Code of Conduct.
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%2funix.stackexchange.com%2fquestions%2f501266%2fecho-to-file-descriptor-overwrites-the-file%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
@Zoonose: When you executecat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you executeexec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.
– P Daddy
16 hours ago
2
Even if youcat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the>>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.
– ilkkachu
10 hours ago
add a comment |
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
@Zoonose: When you executecat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you executeexec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.
– P Daddy
16 hours ago
2
Even if youcat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the>>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.
– ilkkachu
10 hours ago
add a comment |
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
Because you hadn't done any reads on descriptor 88, the current seek position was "0", and so the write took place at that point.
If, instead, you'd read the file before then, then appends happen:
bash-4.2$ cat <&88
The quick brown fox ...
The quick brown fox ...
bash-4.2$ echo hello >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
bash-4.2$ echo more >&88
bash-4.2$ cat example.txt
The quick brown fox ...
The quick brown fox ...
hello
more
answered 18 hours ago
Stephen HarrisStephen Harris
26.2k24577
26.2k24577
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
@Zoonose: When you executecat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you executeexec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.
– P Daddy
16 hours ago
2
Even if youcat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the>>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.
– ilkkachu
10 hours ago
add a comment |
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
@Zoonose: When you executecat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you executeexec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.
– P Daddy
16 hours ago
2
Even if youcat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the>>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.
– ilkkachu
10 hours ago
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Wow! So this means that the file descriptor (in this example 88) maintains a separate seek position to the standard cat? i.e. cat example.txt
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
Thanks Stephen. Just tested this out and you are right. Interestingly enough, if I continue to echo out to the file again, and then echo to the descriptor (without reading on the descriptor) the problem persists. So if other processes are writing to the file, then I need to constantly read in on the descriptor, before writing out!
– Zoonose
17 hours ago
2
2
@Zoonose: When you execute
cat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you execute exec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.– P Daddy
16 hours ago
@Zoonose: When you execute
cat example.txt
, cat opens the file, getting a descriptor with a seek position starting at the beginning of the file, reads it until the end, and then closes the descriptor. When you execute exec 88<>example.txt
, bash opens the file, getting a descriptor with a seek position starting at the beginning of the file. The file itself doesn't maintain a seek position, instead a position is maintained for each open file descriptor.– P Daddy
16 hours ago
2
2
Even if you
cat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the >>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.– ilkkachu
10 hours ago
Even if you
cat <&88
first, the following writes are just regular writes to the position where the writing stopped, not proper appends. They might overwrite data written by another process in the meanwhile. If appending is what is wanted, then the >>
redirection operator is the (only) way to go. As far as I know, Bash doesn't really have a way to seek files, and it also doesn't allow opening with both read/write-mode and append-mode at the same time.– ilkkachu
10 hours ago
add a comment |
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.
New contributor
add a comment |
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.
New contributor
add a comment |
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.
New contributor
As @Zoonose correctly points out, each filedescriptor has its own read-write cursor position within the file that it's connected to. And a file can be opened either by the shell when you use a redirection such as <>
, or by a program such as cat
.
But the numbers that you think of as "a filedescriptor" are just references to the actual filedescriptors within the kernel, and it's entirely normal for one filedescriptor to have multiple such reference numberss, either within a single process, or between processes.
So when you open a terminal window (or log in by ssh), you start with a single filedescriptor open to your terminal, connected as fd#0, fd#1 & fd#2 in your shell process. Any process that the shell starts with inherit these by default -- except where you've used pipes or redirections.
The redirection >>
flags the filedescriptor as O_APPEND
, so that writes through that filedescriptor ignore the cursor and go onto the end of the file.
The redirection >
causes the target file to be truncated just once, before any writing is done. Thus any writing after that normally goes into the empty space past the end of the file.
Writes to a file do not themselves cause truncation; they will simply replace whatever is at the current position, and stretch the end-of-file if necessary.
Note that somecmd >&88
will cause the stdout (fd#1) for somecmd to share the filedescriptor with fd#88 of the current shell. That means it will share the O_APPEND
option, if present. It won't cause it to be truncated again; that's a one-time thing.
What you're seeing in the case is that there's no truncation when you use >&88
, because fd#88 wasn't opened using >>
, and so writes from multiple processes can be interleaved.
New contributor
New contributor
answered 12 hours ago
MartinMartin
211
211
New contributor
New contributor
add a comment |
add a comment |
Zoonose is a new contributor. Be nice, and check out our Code of Conduct.
Zoonose is a new contributor. Be nice, and check out our Code of Conduct.
Zoonose is a new contributor. Be nice, and check out our Code of Conduct.
Zoonose is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- 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%2funix.stackexchange.com%2fquestions%2f501266%2fecho-to-file-descriptor-overwrites-the-file%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