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;









8















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?










share|improve this question





















  • 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 also tail -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

















8















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?










share|improve this question





















  • 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 also tail -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













8












8








8


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?










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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





    What is wrong with echo $(stuff)?

    – Kamil Maciorowski
    Apr 16 at 13:00












  • 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 also tail -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







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










3 Answers
3






active

oldest

votes


















22
















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).






share|improve this answer






















  • 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
















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.






share|improve this answer
































    4
















    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.






    share|improve this answer


























      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
      );



      );














      draft saved

      draft discarded
















      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









      22
















      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).






      share|improve this answer






















      • 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
















      22
















      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).






      share|improve this answer






















      • 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














      22














      22










      22









      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).






      share|improve this answer















      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).







      share|improve this answer














      share|improve this answer



      share|improve this answer








      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













      • 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














      5
















      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.






      share|improve this answer





























        5
















        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.






        share|improve this answer



























          5














          5










          5









          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.






          share|improve this answer













          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Apr 16 at 6:55









          John1024John1024

          52.6k5 gold badges123 silver badges136 bronze badges




          52.6k5 gold badges123 silver badges136 bronze badges
























              4
















              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.






              share|improve this answer





























                4
















                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.






                share|improve this answer



























                  4














                  4










                  4









                  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.






                  share|improve this answer













                  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.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Apr 16 at 6:54









                  ArchemarArchemar

                  21.6k9 gold badges42 silver badges77 bronze badges




                  21.6k9 gold badges42 silver badges77 bronze badges































                      draft saved

                      draft discarded















































                      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.




                      draft saved


                      draft discarded














                      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





















































                      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







                      Popular posts from this blog

                      Tamil (spriik) Luke uk diar | Nawigatjuun

                      Align equal signs while including text over equalitiesAMS align: left aligned text/math plus multicolumn alignmentMultiple alignmentsAligning equations in multiple placesNumbering and aligning an equation with multiple columnsHow to align one equation with another multline equationUsing \ in environments inside the begintabularxNumber equations and preserving alignment of equal signsHow can I align equations to the left and to the right?Double equation alignment problem within align enviromentAligned within align: Why are they right-aligned?

                      Training a classifier when some of the features are unknownWhy does Gradient Boosting regression predict negative values when there are no negative y-values in my training set?How to improve an existing (trained) classifier?What is effect when I set up some self defined predisctor variables?Why Matlab neural network classification returns decimal values on prediction dataset?Fitting and transforming text data in training, testing, and validation setsHow to quantify the performance of the classifier (multi-class SVM) using the test data?How do I control for some patients providing multiple samples in my training data?Training and Test setTraining a convolutional neural network for image denoising in MatlabShouldn't an autoencoder with #(neurons in hidden layer) = #(neurons in input layer) be “perfect”?