bash aliases do not expand even with shopt expand_aliases












5















I want to run an alias inside a bash -c construct.



The bash manual says:




Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt




In this example, why is the alias hi not found when setting expand_aliases explicitly?



% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases on
bash: hi: command not found


I'm running GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).



Context: I want to be able to run an alias at idle priority, eg a script containing:



#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"


I want to avoid using bash -i as I don't want my .bashrc to be read.










share|improve this question




















  • 2





    The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

    – Haxiel
    15 hours ago













  • As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

    – chepner
    8 hours ago
















5















I want to run an alias inside a bash -c construct.



The bash manual says:




Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt




In this example, why is the alias hi not found when setting expand_aliases explicitly?



% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases on
bash: hi: command not found


I'm running GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).



Context: I want to be able to run an alias at idle priority, eg a script containing:



#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"


I want to avoid using bash -i as I don't want my .bashrc to be read.










share|improve this question




















  • 2





    The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

    – Haxiel
    15 hours ago













  • As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

    – chepner
    8 hours ago














5












5








5








I want to run an alias inside a bash -c construct.



The bash manual says:




Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt




In this example, why is the alias hi not found when setting expand_aliases explicitly?



% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases on
bash: hi: command not found


I'm running GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).



Context: I want to be able to run an alias at idle priority, eg a script containing:



#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"


I want to avoid using bash -i as I don't want my .bashrc to be read.










share|improve this question
















I want to run an alias inside a bash -c construct.



The bash manual says:




Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt




In this example, why is the alias hi not found when setting expand_aliases explicitly?



% bash -O expand_aliases -c "alias hi='echo hello'; alias; shopt expand_aliases; hi"
alias hi='echo hello'
expand_aliases on
bash: hi: command not found


I'm running GNU bash, version 5.0.0(1)-release (x86_64-pc-linux-gnu).



Context: I want to be able to run an alias at idle priority, eg a script containing:



#!/bin/bash
exec chrt -i 0 nice -n 19 ionice -c 3 bash -c ". ~/.config/bash/aliases; shopt -s expand_aliases; $(shell-quote "$@")"


I want to avoid using bash -i as I don't want my .bashrc to be read.







bash alias






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 15 hours ago







Tom Hale

















asked 15 hours ago









Tom HaleTom Hale

7,13533797




7,13533797








  • 2





    The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

    – Haxiel
    15 hours ago













  • As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

    – chepner
    8 hours ago














  • 2





    The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

    – Haxiel
    15 hours ago













  • As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

    – chepner
    8 hours ago








2




2





The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

– Haxiel
15 hours ago







The paragraph right after the quoted statement from the Bash manual seems to cover this: '...Aliases are expanded when a command is read, not when it is executed. Therefore, an alias definition appearing on the same line as another command does not take effect until the next line of input is read. The commands following the alias definition on that line are not affected by the new alias....'

– Haxiel
15 hours ago















As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

– chepner
8 hours ago





As in most cases, you should consider using a shell function instead of an alias here. bash -c "hi () { echo hello; }; hi" outputs hello.

– chepner
8 hours ago










2 Answers
2






active

oldest

votes


















11














It doesn't seem work if you set the alias on the same line as it's used. Probably something to do with how aliases are expanded really early in the command line processing, before the actual parsing stage. On an interactive shell:



$ alias foo
bash: alias: foo: not found
$ alias foo='echo foo'; foo # 2
bash: foo: command not found
$ alias foo='echo bar'; foo # 3
foo
$ foo
bar


Note how the alias used is one line late: on the second command it doesn't find the alias just set, and on the third command it uses the one that was previously set.



So, it works if we put a newline within the -c string:



$ bash -c $'shopt -s expand_aliases; alias foo="echo foo";n foo'
foo


(You could also use bash -O expand_aliases -c ... instead of using shopt within the script, not that it helps with the newline.)



Alternatively, you could use a shell function instead of an alias, they're much better in other ways, too:



$ bash -c 'foo() { echo foo; }; foo'
foo





share|improve this answer































    11














    Turning my comment into an answer, as suggested by ilkkachu.



    The Bash manual (linked to in the question) does provide an explanation of how the aliases are handled when there is an alias definition and a command on the same line.



    Quote (slightly formatted for clarity):




    The rules concerning the definition and use of aliases are somewhat
    confusing. Bash always reads at least one complete line of input, and
    all lines that make up a compound command, before executing any of the
    commands on that line or the compound command.



    Aliases are expanded when a command is read, not when it is executed.
    Therefore, an alias definition appearing on the same line as another
    command does not take effect until the next line of input is read. The
    commands following the alias definition on that line are not affected
    by the new alias.



    This behavior is also an issue when functions are executed. Aliases
    are expanded when a function definition is read, not when the function
    is executed, because a function definition is itself a command. As a
    consequence, aliases defined in a function are not available until
    after that function is executed.



    To be safe, always put alias definitions on a separate line, and do
    not use alias in compound commands.




    ilkkachu's answer provides multiple possible solutions to this problem.






    share|improve this answer
























    • FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

      – ilkkachu
      11 hours ago











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


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f502257%2fbash-aliases-do-not-expand-even-with-shopt-expand-aliases%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









    11














    It doesn't seem work if you set the alias on the same line as it's used. Probably something to do with how aliases are expanded really early in the command line processing, before the actual parsing stage. On an interactive shell:



    $ alias foo
    bash: alias: foo: not found
    $ alias foo='echo foo'; foo # 2
    bash: foo: command not found
    $ alias foo='echo bar'; foo # 3
    foo
    $ foo
    bar


    Note how the alias used is one line late: on the second command it doesn't find the alias just set, and on the third command it uses the one that was previously set.



    So, it works if we put a newline within the -c string:



    $ bash -c $'shopt -s expand_aliases; alias foo="echo foo";n foo'
    foo


    (You could also use bash -O expand_aliases -c ... instead of using shopt within the script, not that it helps with the newline.)



    Alternatively, you could use a shell function instead of an alias, they're much better in other ways, too:



    $ bash -c 'foo() { echo foo; }; foo'
    foo





    share|improve this answer




























      11














      It doesn't seem work if you set the alias on the same line as it's used. Probably something to do with how aliases are expanded really early in the command line processing, before the actual parsing stage. On an interactive shell:



      $ alias foo
      bash: alias: foo: not found
      $ alias foo='echo foo'; foo # 2
      bash: foo: command not found
      $ alias foo='echo bar'; foo # 3
      foo
      $ foo
      bar


      Note how the alias used is one line late: on the second command it doesn't find the alias just set, and on the third command it uses the one that was previously set.



      So, it works if we put a newline within the -c string:



      $ bash -c $'shopt -s expand_aliases; alias foo="echo foo";n foo'
      foo


      (You could also use bash -O expand_aliases -c ... instead of using shopt within the script, not that it helps with the newline.)



      Alternatively, you could use a shell function instead of an alias, they're much better in other ways, too:



      $ bash -c 'foo() { echo foo; }; foo'
      foo





      share|improve this answer


























        11












        11








        11







        It doesn't seem work if you set the alias on the same line as it's used. Probably something to do with how aliases are expanded really early in the command line processing, before the actual parsing stage. On an interactive shell:



        $ alias foo
        bash: alias: foo: not found
        $ alias foo='echo foo'; foo # 2
        bash: foo: command not found
        $ alias foo='echo bar'; foo # 3
        foo
        $ foo
        bar


        Note how the alias used is one line late: on the second command it doesn't find the alias just set, and on the third command it uses the one that was previously set.



        So, it works if we put a newline within the -c string:



        $ bash -c $'shopt -s expand_aliases; alias foo="echo foo";n foo'
        foo


        (You could also use bash -O expand_aliases -c ... instead of using shopt within the script, not that it helps with the newline.)



        Alternatively, you could use a shell function instead of an alias, they're much better in other ways, too:



        $ bash -c 'foo() { echo foo; }; foo'
        foo





        share|improve this answer













        It doesn't seem work if you set the alias on the same line as it's used. Probably something to do with how aliases are expanded really early in the command line processing, before the actual parsing stage. On an interactive shell:



        $ alias foo
        bash: alias: foo: not found
        $ alias foo='echo foo'; foo # 2
        bash: foo: command not found
        $ alias foo='echo bar'; foo # 3
        foo
        $ foo
        bar


        Note how the alias used is one line late: on the second command it doesn't find the alias just set, and on the third command it uses the one that was previously set.



        So, it works if we put a newline within the -c string:



        $ bash -c $'shopt -s expand_aliases; alias foo="echo foo";n foo'
        foo


        (You could also use bash -O expand_aliases -c ... instead of using shopt within the script, not that it helps with the newline.)



        Alternatively, you could use a shell function instead of an alias, they're much better in other ways, too:



        $ bash -c 'foo() { echo foo; }; foo'
        foo






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 15 hours ago









        ilkkachuilkkachu

        59.7k895169




        59.7k895169

























            11














            Turning my comment into an answer, as suggested by ilkkachu.



            The Bash manual (linked to in the question) does provide an explanation of how the aliases are handled when there is an alias definition and a command on the same line.



            Quote (slightly formatted for clarity):




            The rules concerning the definition and use of aliases are somewhat
            confusing. Bash always reads at least one complete line of input, and
            all lines that make up a compound command, before executing any of the
            commands on that line or the compound command.



            Aliases are expanded when a command is read, not when it is executed.
            Therefore, an alias definition appearing on the same line as another
            command does not take effect until the next line of input is read. The
            commands following the alias definition on that line are not affected
            by the new alias.



            This behavior is also an issue when functions are executed. Aliases
            are expanded when a function definition is read, not when the function
            is executed, because a function definition is itself a command. As a
            consequence, aliases defined in a function are not available until
            after that function is executed.



            To be safe, always put alias definitions on a separate line, and do
            not use alias in compound commands.




            ilkkachu's answer provides multiple possible solutions to this problem.






            share|improve this answer
























            • FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

              – ilkkachu
              11 hours ago
















            11














            Turning my comment into an answer, as suggested by ilkkachu.



            The Bash manual (linked to in the question) does provide an explanation of how the aliases are handled when there is an alias definition and a command on the same line.



            Quote (slightly formatted for clarity):




            The rules concerning the definition and use of aliases are somewhat
            confusing. Bash always reads at least one complete line of input, and
            all lines that make up a compound command, before executing any of the
            commands on that line or the compound command.



            Aliases are expanded when a command is read, not when it is executed.
            Therefore, an alias definition appearing on the same line as another
            command does not take effect until the next line of input is read. The
            commands following the alias definition on that line are not affected
            by the new alias.



            This behavior is also an issue when functions are executed. Aliases
            are expanded when a function definition is read, not when the function
            is executed, because a function definition is itself a command. As a
            consequence, aliases defined in a function are not available until
            after that function is executed.



            To be safe, always put alias definitions on a separate line, and do
            not use alias in compound commands.




            ilkkachu's answer provides multiple possible solutions to this problem.






            share|improve this answer
























            • FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

              – ilkkachu
              11 hours ago














            11












            11








            11







            Turning my comment into an answer, as suggested by ilkkachu.



            The Bash manual (linked to in the question) does provide an explanation of how the aliases are handled when there is an alias definition and a command on the same line.



            Quote (slightly formatted for clarity):




            The rules concerning the definition and use of aliases are somewhat
            confusing. Bash always reads at least one complete line of input, and
            all lines that make up a compound command, before executing any of the
            commands on that line or the compound command.



            Aliases are expanded when a command is read, not when it is executed.
            Therefore, an alias definition appearing on the same line as another
            command does not take effect until the next line of input is read. The
            commands following the alias definition on that line are not affected
            by the new alias.



            This behavior is also an issue when functions are executed. Aliases
            are expanded when a function definition is read, not when the function
            is executed, because a function definition is itself a command. As a
            consequence, aliases defined in a function are not available until
            after that function is executed.



            To be safe, always put alias definitions on a separate line, and do
            not use alias in compound commands.




            ilkkachu's answer provides multiple possible solutions to this problem.






            share|improve this answer













            Turning my comment into an answer, as suggested by ilkkachu.



            The Bash manual (linked to in the question) does provide an explanation of how the aliases are handled when there is an alias definition and a command on the same line.



            Quote (slightly formatted for clarity):




            The rules concerning the definition and use of aliases are somewhat
            confusing. Bash always reads at least one complete line of input, and
            all lines that make up a compound command, before executing any of the
            commands on that line or the compound command.



            Aliases are expanded when a command is read, not when it is executed.
            Therefore, an alias definition appearing on the same line as another
            command does not take effect until the next line of input is read. The
            commands following the alias definition on that line are not affected
            by the new alias.



            This behavior is also an issue when functions are executed. Aliases
            are expanded when a function definition is read, not when the function
            is executed, because a function definition is itself a command. As a
            consequence, aliases defined in a function are not available until
            after that function is executed.



            To be safe, always put alias definitions on a separate line, and do
            not use alias in compound commands.




            ilkkachu's answer provides multiple possible solutions to this problem.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered 14 hours ago









            HaxielHaxiel

            2,8951917




            2,8951917













            • FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

              – ilkkachu
              11 hours ago



















            • FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

              – ilkkachu
              11 hours ago

















            FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

            – ilkkachu
            11 hours ago





            FWIW, I saw your last comment but didn't have time to answer. It's not a bad thing for answers to complement others, and knowing it's actually documented that way is useful. So thanks for writing this up, now I can upvote it. :)

            – ilkkachu
            11 hours ago


















            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%2f502257%2fbash-aliases-do-not-expand-even-with-shopt-expand-aliases%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

            How to label and detect the document text images

            Vallis Paradisi

            Tabula Rosettana