Echoing a tail command produces unexpected output?Why does cron silently fail to run sudo stuff in my script?BashScript works from Terminal but not from CronTabIs this tail behavior in Grouping Commands specified by POSIX?How to run a shell script using cron and atWhy does head; tail on a large file sometimes take a long time and sometimes not?
Anonymous reviewer disclosed his identity. Should I thank him by name?
Why do personal finance apps focus on outgoings rather than income
Why does the Pilatus PC-24 have such a large "Wing Support"?
Why do many websites hide input when entering a OTP
Writing about real people - not giving offence
Can Fabled Passage generate two mana with Amulet of Vigor?
Why Vegetable Stock is bitter, but Chicken Stock not?
Could the Queen overturn the UK Supreme Court ruling regarding prorogation of Parliament?
Job interview by video at home and privacy concerns
What's the correct way to determine turn order in this situation?
Present participles of the verb esse
Generating numbers with cubes
Chain on singlespeed tight, pedals won't turn backwards very freely - is this an issue?
How to level a picture frame hung on a single nail?
Lighthouse Alternatives
What did the Federation give the Prophets in exchange for access to the wormhole in DS9?
Why is there such a singular place for bird watching?
Did Joe Biden "stop a prosecution" into his son in Ukraine? And did he brag about stopping the prosecution?
The answer is a girl's name (my future granddaughter) - can anyone help?
Why not add cuspidal curves in the moduli space of stable curves?
Young adult short story book with one story where a woman finds a walrus suit and becomes a walrus
French license plates
Would a horse be sufficient buffer to prevent injury when falling from a great height?
What is the point of impeaching Trump?
Echoing a tail command produces unexpected output?
Why does cron silently fail to run sudo stuff in my script?BashScript works from Terminal but not from CronTabIs this tail behavior in Grouping Commands specified by POSIX?How to run a shell script using cron and atWhy does head; tail on a large file sometimes take a long time and sometimes not?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
This command, when run alone, produces the expected result (the last line of the crontab):
tail -n 1 /etc/crontab
However, when I run it as part of an echo command to send the result to a file, it adds a summary of all the files in the working directory, plus the expected result:
sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'
Why did this command produce the extra data?
bash sudo cron echo tail
add a comment
|
This command, when run alone, produces the expected result (the last line of the crontab):
tail -n 1 /etc/crontab
However, when I run it as part of an echo command to send the result to a file, it adds a summary of all the files in the working directory, plus the expected result:
sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'
Why did this command produce the extra data?
bash sudo cron echo tail
2
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
3
What isecho
doing for you here? Consider alsotail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
1
What is wrong withecho $(stuff)
?
– Kamil Maciorowski
Apr 16 at 13:00
add a comment
|
This command, when run alone, produces the expected result (the last line of the crontab):
tail -n 1 /etc/crontab
However, when I run it as part of an echo command to send the result to a file, it adds a summary of all the files in the working directory, plus the expected result:
sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'
Why did this command produce the extra data?
bash sudo cron echo tail
This command, when run alone, produces the expected result (the last line of the crontab):
tail -n 1 /etc/crontab
However, when I run it as part of an echo command to send the result to a file, it adds a summary of all the files in the working directory, plus the expected result:
sudo bash -c 'echo $(tail -n 1 /etc/crontab) > /path/to/file'
Why did this command produce the extra data?
bash sudo cron echo tail
bash sudo cron echo tail
edited Apr 16 at 12:43
Jeff Schaller♦
50.1k11 gold badges74 silver badges166 bronze badges
50.1k11 gold badges74 silver badges166 bronze badges
asked Apr 16 at 6:46
DavidwDavidw
1531 gold badge1 silver badge9 bronze badges
1531 gold badge1 silver badge9 bronze badges
2
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
3
What isecho
doing for you here? Consider alsotail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
1
What is wrong withecho $(stuff)
?
– Kamil Maciorowski
Apr 16 at 13:00
add a comment
|
2
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
3
What isecho
doing for you here? Consider alsotail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
1
What is wrong withecho $(stuff)
?
– Kamil Maciorowski
Apr 16 at 13:00
2
2
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
3
3
What is
echo
doing for you here? Consider also tail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
What is
echo
doing for you here? Consider also tail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
1
1
What is wrong with
echo $(stuff)
?– Kamil Maciorowski
Apr 16 at 13:00
What is wrong with
echo $(stuff)
?– Kamil Maciorowski
Apr 16 at 13:00
add a comment
|
3 Answers
3
active
oldest
votes
Your crontab line has one or more asterisks *
in it, indicating "any time". When that line is substituted in from the command substitution, the result is something like
echo * * * * * cmd > /path/to/file
While most further expansions are not applied to the output of command substitution, pathname expansion is (as is field splitting):
The results of command substitution shall not be processed for further tilde expansion, parameter expansion, command substitution, or arithmetic expansion. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.
Pathname expansion is what turns *.txt
into a list of matching filenames (globbing), where *
matches everything. The end result is that you get every (non-hidden) filename in the working directory listed for every *
in your crontab line.
You could fix this by quoting the expansion, if the code you posted was a representative of a more complex command:
sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'
but more straightforwardly just lose the echo
entirely:
sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'
This should do what you want and it's simpler as well (the only other material difference is that this version will omit field splitting that would otherwise have occurred, so runs of spaces won't be collapsed).
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.
– Bass
Apr 16 at 8:22
add a comment
|
Let's consider a directory with these files:
$ ls
crontab file1 file2 file3
$ cat crontab
f*
Now, let's run the tail command:
$ tail -n 1 crontab
f*
The above is the last line of crontab
and this is what we expect. However:
$ echo $(tail -n 1 crontab)
file1 file2 file3
Double-quotes eliminate this problem:
$ echo "$(tail -n 1 crontab)"
f*
Without the double-quotes, the result of the command substitution is expanded by the shell. One of the expansions is pathname expansion. In the case above, this means that f*
is expanded to match every file name that starts with f
.
Unless you explicitly want shell expansions, put all you shell variables and/or command substitutions inside double quotes.
add a comment
|
globing shell mecanism will expand *
to local file.
crontab line is likely to have a *
as placeholder for any.
e.g. this line in crontab run on 7.47 am on sunday, first star mean any day, second any month.
47 7 * * 0 /run/on/sunday
then you tail
, and issue
echo 47 7 * * 0 /run/on/sunday
that will expand *
to local file.
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/4.0/"u003ecc by-sa 4.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%2funix.stackexchange.com%2fquestions%2f512702%2fechoing-a-tail-command-produces-unexpected-output%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your crontab line has one or more asterisks *
in it, indicating "any time". When that line is substituted in from the command substitution, the result is something like
echo * * * * * cmd > /path/to/file
While most further expansions are not applied to the output of command substitution, pathname expansion is (as is field splitting):
The results of command substitution shall not be processed for further tilde expansion, parameter expansion, command substitution, or arithmetic expansion. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.
Pathname expansion is what turns *.txt
into a list of matching filenames (globbing), where *
matches everything. The end result is that you get every (non-hidden) filename in the working directory listed for every *
in your crontab line.
You could fix this by quoting the expansion, if the code you posted was a representative of a more complex command:
sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'
but more straightforwardly just lose the echo
entirely:
sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'
This should do what you want and it's simpler as well (the only other material difference is that this version will omit field splitting that would otherwise have occurred, so runs of spaces won't be collapsed).
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.
– Bass
Apr 16 at 8:22
add a comment
|
Your crontab line has one or more asterisks *
in it, indicating "any time". When that line is substituted in from the command substitution, the result is something like
echo * * * * * cmd > /path/to/file
While most further expansions are not applied to the output of command substitution, pathname expansion is (as is field splitting):
The results of command substitution shall not be processed for further tilde expansion, parameter expansion, command substitution, or arithmetic expansion. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.
Pathname expansion is what turns *.txt
into a list of matching filenames (globbing), where *
matches everything. The end result is that you get every (non-hidden) filename in the working directory listed for every *
in your crontab line.
You could fix this by quoting the expansion, if the code you posted was a representative of a more complex command:
sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'
but more straightforwardly just lose the echo
entirely:
sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'
This should do what you want and it's simpler as well (the only other material difference is that this version will omit field splitting that would otherwise have occurred, so runs of spaces won't be collapsed).
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.
– Bass
Apr 16 at 8:22
add a comment
|
Your crontab line has one or more asterisks *
in it, indicating "any time". When that line is substituted in from the command substitution, the result is something like
echo * * * * * cmd > /path/to/file
While most further expansions are not applied to the output of command substitution, pathname expansion is (as is field splitting):
The results of command substitution shall not be processed for further tilde expansion, parameter expansion, command substitution, or arithmetic expansion. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.
Pathname expansion is what turns *.txt
into a list of matching filenames (globbing), where *
matches everything. The end result is that you get every (non-hidden) filename in the working directory listed for every *
in your crontab line.
You could fix this by quoting the expansion, if the code you posted was a representative of a more complex command:
sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'
but more straightforwardly just lose the echo
entirely:
sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'
This should do what you want and it's simpler as well (the only other material difference is that this version will omit field splitting that would otherwise have occurred, so runs of spaces won't be collapsed).
Your crontab line has one or more asterisks *
in it, indicating "any time". When that line is substituted in from the command substitution, the result is something like
echo * * * * * cmd > /path/to/file
While most further expansions are not applied to the output of command substitution, pathname expansion is (as is field splitting):
The results of command substitution shall not be processed for further tilde expansion, parameter expansion, command substitution, or arithmetic expansion. If a command substitution occurs inside double-quotes, field splitting and pathname expansion shall not be performed on the results of the substitution.
Pathname expansion is what turns *.txt
into a list of matching filenames (globbing), where *
matches everything. The end result is that you get every (non-hidden) filename in the working directory listed for every *
in your crontab line.
You could fix this by quoting the expansion, if the code you posted was a representative of a more complex command:
sudo bash -c 'echo "$(tail -n 1 /etc/crontab)" > /path/to/file'
but more straightforwardly just lose the echo
entirely:
sudo bash -c 'tail -n 1 /etc/crontab > /path/to/file'
This should do what you want and it's simpler as well (the only other material difference is that this version will omit field splitting that would otherwise have occurred, so runs of spaces won't be collapsed).
edited Apr 16 at 7:02
answered Apr 16 at 6:54
Michael HomerMichael Homer
55.5k9 gold badges156 silver badges190 bronze badges
55.5k9 gold badges156 silver badges190 bronze badges
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.
– Bass
Apr 16 at 8:22
add a comment
|
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.
– Bass
Apr 16 at 8:22
5
5
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:
tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.– Bass
Apr 16 at 8:22
Since /etc/crontab is almost always world readable, all the "bash -c" trickery is actually unnecessary:
tail -n -1 /etc/crontab | sudo tee /path/to/file
is the idiom that I've found to be the least error prone when redirecting output into files that require superuser privileges.– Bass
Apr 16 at 8:22
add a comment
|
Let's consider a directory with these files:
$ ls
crontab file1 file2 file3
$ cat crontab
f*
Now, let's run the tail command:
$ tail -n 1 crontab
f*
The above is the last line of crontab
and this is what we expect. However:
$ echo $(tail -n 1 crontab)
file1 file2 file3
Double-quotes eliminate this problem:
$ echo "$(tail -n 1 crontab)"
f*
Without the double-quotes, the result of the command substitution is expanded by the shell. One of the expansions is pathname expansion. In the case above, this means that f*
is expanded to match every file name that starts with f
.
Unless you explicitly want shell expansions, put all you shell variables and/or command substitutions inside double quotes.
add a comment
|
Let's consider a directory with these files:
$ ls
crontab file1 file2 file3
$ cat crontab
f*
Now, let's run the tail command:
$ tail -n 1 crontab
f*
The above is the last line of crontab
and this is what we expect. However:
$ echo $(tail -n 1 crontab)
file1 file2 file3
Double-quotes eliminate this problem:
$ echo "$(tail -n 1 crontab)"
f*
Without the double-quotes, the result of the command substitution is expanded by the shell. One of the expansions is pathname expansion. In the case above, this means that f*
is expanded to match every file name that starts with f
.
Unless you explicitly want shell expansions, put all you shell variables and/or command substitutions inside double quotes.
add a comment
|
Let's consider a directory with these files:
$ ls
crontab file1 file2 file3
$ cat crontab
f*
Now, let's run the tail command:
$ tail -n 1 crontab
f*
The above is the last line of crontab
and this is what we expect. However:
$ echo $(tail -n 1 crontab)
file1 file2 file3
Double-quotes eliminate this problem:
$ echo "$(tail -n 1 crontab)"
f*
Without the double-quotes, the result of the command substitution is expanded by the shell. One of the expansions is pathname expansion. In the case above, this means that f*
is expanded to match every file name that starts with f
.
Unless you explicitly want shell expansions, put all you shell variables and/or command substitutions inside double quotes.
Let's consider a directory with these files:
$ ls
crontab file1 file2 file3
$ cat crontab
f*
Now, let's run the tail command:
$ tail -n 1 crontab
f*
The above is the last line of crontab
and this is what we expect. However:
$ echo $(tail -n 1 crontab)
file1 file2 file3
Double-quotes eliminate this problem:
$ echo "$(tail -n 1 crontab)"
f*
Without the double-quotes, the result of the command substitution is expanded by the shell. One of the expansions is pathname expansion. In the case above, this means that f*
is expanded to match every file name that starts with f
.
Unless you explicitly want shell expansions, put all you shell variables and/or command substitutions inside double quotes.
answered Apr 16 at 6:55
John1024John1024
52.6k5 gold badges123 silver badges136 bronze badges
52.6k5 gold badges123 silver badges136 bronze badges
add a comment
|
add a comment
|
globing shell mecanism will expand *
to local file.
crontab line is likely to have a *
as placeholder for any.
e.g. this line in crontab run on 7.47 am on sunday, first star mean any day, second any month.
47 7 * * 0 /run/on/sunday
then you tail
, and issue
echo 47 7 * * 0 /run/on/sunday
that will expand *
to local file.
add a comment
|
globing shell mecanism will expand *
to local file.
crontab line is likely to have a *
as placeholder for any.
e.g. this line in crontab run on 7.47 am on sunday, first star mean any day, second any month.
47 7 * * 0 /run/on/sunday
then you tail
, and issue
echo 47 7 * * 0 /run/on/sunday
that will expand *
to local file.
add a comment
|
globing shell mecanism will expand *
to local file.
crontab line is likely to have a *
as placeholder for any.
e.g. this line in crontab run on 7.47 am on sunday, first star mean any day, second any month.
47 7 * * 0 /run/on/sunday
then you tail
, and issue
echo 47 7 * * 0 /run/on/sunday
that will expand *
to local file.
globing shell mecanism will expand *
to local file.
crontab line is likely to have a *
as placeholder for any.
e.g. this line in crontab run on 7.47 am on sunday, first star mean any day, second any month.
47 7 * * 0 /run/on/sunday
then you tail
, and issue
echo 47 7 * * 0 /run/on/sunday
that will expand *
to local file.
answered Apr 16 at 6:54
ArchemarArchemar
21.6k9 gold badges42 silver badges77 bronze badges
21.6k9 gold badges42 silver badges77 bronze badges
add a comment
|
add a comment
|
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%2f512702%2fechoing-a-tail-command-produces-unexpected-output%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
2
See Why does my shell script choke on whitespace or other special characters? and Why is printf better than echo?
– Stéphane Chazelas
Apr 16 at 6:59
3
What is
echo
doing for you here? Consider alsotail -n 1 /etc/crontab | sudo tee /path/to/file >/dev/null
– ctrl-alt-delor
Apr 16 at 9:12
1
What is wrong with
echo $(stuff)
?– Kamil Maciorowski
Apr 16 at 13:00