bash does not autocomplete my command when using sudo?












6















I'm using SaltStack. I would like to auto-complete the minion name when calling the salt command.



The following line has been added into ~/.bashrc:



complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


Then typing salt inTabsalt integration-Tab; I can see it works as expected:



$ salt integration-TabTab
integration-c integration-u integration-u2


To use with sudo, I have added complete -cf sudo into ~/.bashrc, but it didn't work:




    sudo salt inTab


    returned nothing.



    I also have tried to install bash_completion and added the following lines to ~/.bash_profile:



    if [ -f $(brew --prefix)/etc/bash_completion ]; then
    . $(brew --prefix)/etc/bash_completion
    fi


    but no luck.



    Did I miss something?





    Update



    Oh, the first thing I would like to say is sometimes it works:



    $ sudo salt integration-TabTab
    integration-c integration-u integration-u2


    and sometimes it doesn't.




    So first, let's see how much your bash_completion package does.




    How can I check that? Here's my function:



    # a wrapper method for the next one, when the offset is unknown
    _command()
    {
    local offset i

    # find actual offset, as position of the first non-option
    offset=1
    for (( i=1; i <= COMP_CWORD; i++ )); do
    if [[ "${COMP_WORDS[i]}" != -* ]]; then
    offset=$i
    break
    fi
    done
    _command_offset $offset
    }

    # A meta-command completion function for commands like sudo(8), which need to
    # first complete on a command, then complete according to that command's own
    # completion definition - currently not quite foolproof (e.g. mount and umount
    # don't work properly), but still quite useful.
    #
    _command_offset()
    {
    local cur func cline cspec noglob cmd i char_offset word_offset
    _COMMAND_FUNC _COMMAND_FUNC_ARGS

    word_offset=$1

    # rewrite current completion context before invoking
    # actual command completion

    # find new first word position, then
    # rewrite COMP_LINE and adjust COMP_POINT
    local first_word=${COMP_WORDS[$word_offset]}
    for (( i=0; i <= ${#COMP_LINE}; i++ )); do
    if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
    char_offset=$i
    break
    fi
    done
    COMP_LINE=${COMP_LINE:$char_offset}
    COMP_POINT=$(( COMP_POINT - $char_offset ))

    # shift COMP_WORDS elements and adjust COMP_CWORD
    for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
    COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
    done
    for (( i; i <= COMP_CWORD; i++ )); do
    unset COMP_WORDS[i];
    done
    COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

    COMPREPLY=()
    _get_comp_words_by_ref cur

    if [[ $COMP_CWORD -eq 0 ]]; then
    _compopt_o_filenames
    COMPREPLY=( $( compgen -c -- "$cur" ) )
    else
    cmd=${COMP_WORDS[0]}
    if complete -p ${cmd##*/} &>/dev/null; then
    cspec=$( complete -p ${cmd##*/} )
    if [ "${cspec#* -F }" != "$cspec" ]; then
    # complete -F <function>

    # get function name
    func=${cspec#*-F }
    func=${func%% *}

    if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
    else
    $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
    fi

    # remove any : generated by a command that doesn't
    # default to filenames or dirnames (e.g. sudo chown)
    # FIXME: I'm pretty sure this does not work!
    if [ "${cspec#*-o }" != "$cspec" ]; then
    cspec=${cspec#*-o }
    cspec=${cspec%% *}
    if [[ "$cspec" != @(dir|file)names ]]; then
    COMPREPLY=("${COMPREPLY[@]//\\:/:}")
    else
    _compopt_o_filenames
    fi
    fi
    elif [ -n "$cspec" ]; then
    cspec=${cspec#complete};
    cspec=${cspec%%${cmd##*/}};
    COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
    fi
    elif [ ${#COMPREPLY[@]} -eq 0 ]; then
    _filedir
    fi
    fi
    }





    if you type sudo mkdirTabTab,
    does it show a list of directories?




    Yes:



    $ sudo mkdir TabTab
    .FontForge/ .djangopypi2/ .ievms/ .ssh/ .wireshark-etc/









    share|improve this question




















    • 1





      Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

      – Mark Plotnick
      Jul 11 '14 at 14:38













    • @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

      – quanta
      Jul 12 '14 at 4:49






    • 1





      If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

      – Mark Plotnick
      Jul 14 '14 at 21:29













    • Possibly related: How does Bash path completion work with sudo?

      – G-Man
      Jun 27 '15 at 8:41
















    6















    I'm using SaltStack. I would like to auto-complete the minion name when calling the salt command.



    The following line has been added into ~/.bashrc:



    complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


    Then typing salt inTabsalt integration-Tab; I can see it works as expected:



    $ salt integration-TabTab
    integration-c integration-u integration-u2


    To use with sudo, I have added complete -cf sudo into ~/.bashrc, but it didn't work:




      sudo salt inTab


      returned nothing.



      I also have tried to install bash_completion and added the following lines to ~/.bash_profile:



      if [ -f $(brew --prefix)/etc/bash_completion ]; then
      . $(brew --prefix)/etc/bash_completion
      fi


      but no luck.



      Did I miss something?





      Update



      Oh, the first thing I would like to say is sometimes it works:



      $ sudo salt integration-TabTab
      integration-c integration-u integration-u2


      and sometimes it doesn't.




      So first, let's see how much your bash_completion package does.




      How can I check that? Here's my function:



      # a wrapper method for the next one, when the offset is unknown
      _command()
      {
      local offset i

      # find actual offset, as position of the first non-option
      offset=1
      for (( i=1; i <= COMP_CWORD; i++ )); do
      if [[ "${COMP_WORDS[i]}" != -* ]]; then
      offset=$i
      break
      fi
      done
      _command_offset $offset
      }

      # A meta-command completion function for commands like sudo(8), which need to
      # first complete on a command, then complete according to that command's own
      # completion definition - currently not quite foolproof (e.g. mount and umount
      # don't work properly), but still quite useful.
      #
      _command_offset()
      {
      local cur func cline cspec noglob cmd i char_offset word_offset
      _COMMAND_FUNC _COMMAND_FUNC_ARGS

      word_offset=$1

      # rewrite current completion context before invoking
      # actual command completion

      # find new first word position, then
      # rewrite COMP_LINE and adjust COMP_POINT
      local first_word=${COMP_WORDS[$word_offset]}
      for (( i=0; i <= ${#COMP_LINE}; i++ )); do
      if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
      char_offset=$i
      break
      fi
      done
      COMP_LINE=${COMP_LINE:$char_offset}
      COMP_POINT=$(( COMP_POINT - $char_offset ))

      # shift COMP_WORDS elements and adjust COMP_CWORD
      for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
      COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
      done
      for (( i; i <= COMP_CWORD; i++ )); do
      unset COMP_WORDS[i];
      done
      COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

      COMPREPLY=()
      _get_comp_words_by_ref cur

      if [[ $COMP_CWORD -eq 0 ]]; then
      _compopt_o_filenames
      COMPREPLY=( $( compgen -c -- "$cur" ) )
      else
      cmd=${COMP_WORDS[0]}
      if complete -p ${cmd##*/} &>/dev/null; then
      cspec=$( complete -p ${cmd##*/} )
      if [ "${cspec#* -F }" != "$cspec" ]; then
      # complete -F <function>

      # get function name
      func=${cspec#*-F }
      func=${func%% *}

      if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
      $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
      else
      $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
      fi

      # remove any : generated by a command that doesn't
      # default to filenames or dirnames (e.g. sudo chown)
      # FIXME: I'm pretty sure this does not work!
      if [ "${cspec#*-o }" != "$cspec" ]; then
      cspec=${cspec#*-o }
      cspec=${cspec%% *}
      if [[ "$cspec" != @(dir|file)names ]]; then
      COMPREPLY=("${COMPREPLY[@]//\\:/:}")
      else
      _compopt_o_filenames
      fi
      fi
      elif [ -n "$cspec" ]; then
      cspec=${cspec#complete};
      cspec=${cspec%%${cmd##*/}};
      COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
      fi
      elif [ ${#COMPREPLY[@]} -eq 0 ]; then
      _filedir
      fi
      fi
      }





      if you type sudo mkdirTabTab,
      does it show a list of directories?




      Yes:



      $ sudo mkdir TabTab
      .FontForge/ .djangopypi2/ .ievms/ .ssh/ .wireshark-etc/









      share|improve this question




















      • 1





        Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

        – Mark Plotnick
        Jul 11 '14 at 14:38













      • @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

        – quanta
        Jul 12 '14 at 4:49






      • 1





        If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

        – Mark Plotnick
        Jul 14 '14 at 21:29













      • Possibly related: How does Bash path completion work with sudo?

        – G-Man
        Jun 27 '15 at 8:41














      6












      6








      6








      I'm using SaltStack. I would like to auto-complete the minion name when calling the salt command.



      The following line has been added into ~/.bashrc:



      complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


      Then typing salt inTabsalt integration-Tab; I can see it works as expected:



      $ salt integration-TabTab
      integration-c integration-u integration-u2


      To use with sudo, I have added complete -cf sudo into ~/.bashrc, but it didn't work:




        sudo salt inTab


        returned nothing.



        I also have tried to install bash_completion and added the following lines to ~/.bash_profile:



        if [ -f $(brew --prefix)/etc/bash_completion ]; then
        . $(brew --prefix)/etc/bash_completion
        fi


        but no luck.



        Did I miss something?





        Update



        Oh, the first thing I would like to say is sometimes it works:



        $ sudo salt integration-TabTab
        integration-c integration-u integration-u2


        and sometimes it doesn't.




        So first, let's see how much your bash_completion package does.




        How can I check that? Here's my function:



        # a wrapper method for the next one, when the offset is unknown
        _command()
        {
        local offset i

        # find actual offset, as position of the first non-option
        offset=1
        for (( i=1; i <= COMP_CWORD; i++ )); do
        if [[ "${COMP_WORDS[i]}" != -* ]]; then
        offset=$i
        break
        fi
        done
        _command_offset $offset
        }

        # A meta-command completion function for commands like sudo(8), which need to
        # first complete on a command, then complete according to that command's own
        # completion definition - currently not quite foolproof (e.g. mount and umount
        # don't work properly), but still quite useful.
        #
        _command_offset()
        {
        local cur func cline cspec noglob cmd i char_offset word_offset
        _COMMAND_FUNC _COMMAND_FUNC_ARGS

        word_offset=$1

        # rewrite current completion context before invoking
        # actual command completion

        # find new first word position, then
        # rewrite COMP_LINE and adjust COMP_POINT
        local first_word=${COMP_WORDS[$word_offset]}
        for (( i=0; i <= ${#COMP_LINE}; i++ )); do
        if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
        char_offset=$i
        break
        fi
        done
        COMP_LINE=${COMP_LINE:$char_offset}
        COMP_POINT=$(( COMP_POINT - $char_offset ))

        # shift COMP_WORDS elements and adjust COMP_CWORD
        for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
        COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
        done
        for (( i; i <= COMP_CWORD; i++ )); do
        unset COMP_WORDS[i];
        done
        COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

        COMPREPLY=()
        _get_comp_words_by_ref cur

        if [[ $COMP_CWORD -eq 0 ]]; then
        _compopt_o_filenames
        COMPREPLY=( $( compgen -c -- "$cur" ) )
        else
        cmd=${COMP_WORDS[0]}
        if complete -p ${cmd##*/} &>/dev/null; then
        cspec=$( complete -p ${cmd##*/} )
        if [ "${cspec#* -F }" != "$cspec" ]; then
        # complete -F <function>

        # get function name
        func=${cspec#*-F }
        func=${func%% *}

        if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
        $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
        else
        $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
        fi

        # remove any : generated by a command that doesn't
        # default to filenames or dirnames (e.g. sudo chown)
        # FIXME: I'm pretty sure this does not work!
        if [ "${cspec#*-o }" != "$cspec" ]; then
        cspec=${cspec#*-o }
        cspec=${cspec%% *}
        if [[ "$cspec" != @(dir|file)names ]]; then
        COMPREPLY=("${COMPREPLY[@]//\\:/:}")
        else
        _compopt_o_filenames
        fi
        fi
        elif [ -n "$cspec" ]; then
        cspec=${cspec#complete};
        cspec=${cspec%%${cmd##*/}};
        COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
        fi
        elif [ ${#COMPREPLY[@]} -eq 0 ]; then
        _filedir
        fi
        fi
        }





        if you type sudo mkdirTabTab,
        does it show a list of directories?




        Yes:



        $ sudo mkdir TabTab
        .FontForge/ .djangopypi2/ .ievms/ .ssh/ .wireshark-etc/









        share|improve this question
















        I'm using SaltStack. I would like to auto-complete the minion name when calling the salt command.



        The following line has been added into ~/.bashrc:



        complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


        Then typing salt inTabsalt integration-Tab; I can see it works as expected:



        $ salt integration-TabTab
        integration-c integration-u integration-u2


        To use with sudo, I have added complete -cf sudo into ~/.bashrc, but it didn't work:




          sudo salt inTab


          returned nothing.



          I also have tried to install bash_completion and added the following lines to ~/.bash_profile:



          if [ -f $(brew --prefix)/etc/bash_completion ]; then
          . $(brew --prefix)/etc/bash_completion
          fi


          but no luck.



          Did I miss something?





          Update



          Oh, the first thing I would like to say is sometimes it works:



          $ sudo salt integration-TabTab
          integration-c integration-u integration-u2


          and sometimes it doesn't.




          So first, let's see how much your bash_completion package does.




          How can I check that? Here's my function:



          # a wrapper method for the next one, when the offset is unknown
          _command()
          {
          local offset i

          # find actual offset, as position of the first non-option
          offset=1
          for (( i=1; i <= COMP_CWORD; i++ )); do
          if [[ "${COMP_WORDS[i]}" != -* ]]; then
          offset=$i
          break
          fi
          done
          _command_offset $offset
          }

          # A meta-command completion function for commands like sudo(8), which need to
          # first complete on a command, then complete according to that command's own
          # completion definition - currently not quite foolproof (e.g. mount and umount
          # don't work properly), but still quite useful.
          #
          _command_offset()
          {
          local cur func cline cspec noglob cmd i char_offset word_offset
          _COMMAND_FUNC _COMMAND_FUNC_ARGS

          word_offset=$1

          # rewrite current completion context before invoking
          # actual command completion

          # find new first word position, then
          # rewrite COMP_LINE and adjust COMP_POINT
          local first_word=${COMP_WORDS[$word_offset]}
          for (( i=0; i <= ${#COMP_LINE}; i++ )); do
          if [[ "${COMP_LINE:$i:${#first_word}}" == "$first_word" ]]; then
          char_offset=$i
          break
          fi
          done
          COMP_LINE=${COMP_LINE:$char_offset}
          COMP_POINT=$(( COMP_POINT - $char_offset ))

          # shift COMP_WORDS elements and adjust COMP_CWORD
          for (( i=0; i <= COMP_CWORD - $word_offset; i++ )); do
          COMP_WORDS[i]=${COMP_WORDS[i+$word_offset]}
          done
          for (( i; i <= COMP_CWORD; i++ )); do
          unset COMP_WORDS[i];
          done
          COMP_CWORD=$(( $COMP_CWORD - $word_offset ))

          COMPREPLY=()
          _get_comp_words_by_ref cur

          if [[ $COMP_CWORD -eq 0 ]]; then
          _compopt_o_filenames
          COMPREPLY=( $( compgen -c -- "$cur" ) )
          else
          cmd=${COMP_WORDS[0]}
          if complete -p ${cmd##*/} &>/dev/null; then
          cspec=$( complete -p ${cmd##*/} )
          if [ "${cspec#* -F }" != "$cspec" ]; then
          # complete -F <function>

          # get function name
          func=${cspec#*-F }
          func=${func%% *}

          if [[ ${#COMP_WORDS[@]} -ge 2 ]]; then
          $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}" "${COMP_WORDS[${#COMP_WORDS[@]}-2]}"
          else
          $func $cmd "${COMP_WORDS[${#COMP_WORDS[@]}-1]}"
          fi

          # remove any : generated by a command that doesn't
          # default to filenames or dirnames (e.g. sudo chown)
          # FIXME: I'm pretty sure this does not work!
          if [ "${cspec#*-o }" != "$cspec" ]; then
          cspec=${cspec#*-o }
          cspec=${cspec%% *}
          if [[ "$cspec" != @(dir|file)names ]]; then
          COMPREPLY=("${COMPREPLY[@]//\\:/:}")
          else
          _compopt_o_filenames
          fi
          fi
          elif [ -n "$cspec" ]; then
          cspec=${cspec#complete};
          cspec=${cspec%%${cmd##*/}};
          COMPREPLY=( $( eval compgen "$cspec" -- "$cur" ) );
          fi
          elif [ ${#COMPREPLY[@]} -eq 0 ]; then
          _filedir
          fi
          fi
          }





          if you type sudo mkdirTabTab,
          does it show a list of directories?




          Yes:



          $ sudo mkdir TabTab
          .FontForge/ .djangopypi2/ .ievms/ .ssh/ .wireshark-etc/






          bash osx sudo autocomplete






          share|improve this question















          share|improve this question













          share|improve this question




          share|improve this question








          edited Jun 27 '15 at 8:33









          G-Man

          13.1k93465




          13.1k93465










          asked Jul 7 '14 at 8:58









          quantaquanta

          1,0801923




          1,0801923








          • 1





            Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

            – Mark Plotnick
            Jul 11 '14 at 14:38













          • @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

            – quanta
            Jul 12 '14 at 4:49






          • 1





            If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

            – Mark Plotnick
            Jul 14 '14 at 21:29













          • Possibly related: How does Bash path completion work with sudo?

            – G-Man
            Jun 27 '15 at 8:41














          • 1





            Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

            – Mark Plotnick
            Jul 11 '14 at 14:38













          • @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

            – quanta
            Jul 12 '14 at 4:49






          • 1





            If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

            – Mark Plotnick
            Jul 14 '14 at 21:29













          • Possibly related: How does Bash path completion work with sudo?

            – G-Man
            Jun 27 '15 at 8:41








          1




          1





          Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

          – Mark Plotnick
          Jul 11 '14 at 14:38







          Chaining together command completions usually involves completion functions that invoke a function defined in the completion package called _command_offset. So first, let's see how much your bash_completion package does. If you remove the complete -cf sudo line from .bashrc, then logout and login again, and just use the support built in to bash_completion, do you see any special handling at all for sudo, e.g., if you type sudo mkdir <tab><tab>, does it show a list of directories?

          – Mark Plotnick
          Jul 11 '14 at 14:38















          @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

          – quanta
          Jul 12 '14 at 4:49





          @MarkPlotnick: if you type sudo mkdir <tab><tab>, does it show a list of directories? --> Yes, see my update in the original question.

          – quanta
          Jul 12 '14 at 4:49




          1




          1





          If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

          – Mark Plotnick
          Jul 14 '14 at 21:29







          If completion chaining is sometimes working and sometimes not, the first thing I'd check is the completion definition for sudo when completions are not working. Do this by typing complete|grep sudo. Bash on OSX reads its init files in nonintuitive ways (see apple.stackexchange.com/a/13019), so my hunch is that sometimes not all your completion definitions are being read in or they are being superseded by unwanted definitions.

          – Mark Plotnick
          Jul 14 '14 at 21:29















          Possibly related: How does Bash path completion work with sudo?

          – G-Man
          Jun 27 '15 at 8:41





          Possibly related: How does Bash path completion work with sudo?

          – G-Man
          Jun 27 '15 at 8:41










          3 Answers
          3






          active

          oldest

          votes


















          1














          Check set -o to see if maybe posix mode is enabled. If so, disable with set +o posix



          In "posix" mode, bash's tab-completion is for some reason disabled in "vi-mode". I've not seen any explanation why this behavior is so, nor why it's specific to vi-mode, so I didn't bother explaining.



          PS: This answer is more suited for someone who stumbles upon the question via a search engine... not for your particular setup.



          Update:

          Chet Ramey says:




          in POSIX mode, the vi editing mode should not map tab to complete.
          This is because POSIX.2 completely specifies the behavior of the vi
          editing mode, and the standard requires tab to be mapped to self
          insert by default.







          share|improve this answer





















          • 1





            Question about bash completion on posix mode

            – Evgeny Vereshchagin
            Jun 28 '15 at 3:01



















          1














          Quick answer:




          • Install bash-completion

          • Source bash_completion on Bash startup

          • Add your compspec on Bash startup

          • Don't overwrite sudo compspec with complete -cf sudo


          I suppose that you use MacOSX with brew.



          Try:



          brew update
          brew install bash-completion
          brew info bash-completion
          # bash-completion: stable 1.3
          . $(brew --prefix)/etc/bash_completion
          complete -p sudo


          You should see something like this:



          complete -F _root_command sudo


          Test:



          function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
          complete -F _comp_foo foo


          Type foo SpaceTabTab

          You should see a b c



          Type sudo foo SpaceTabTab

          You should see a b c



          Then remove complete -fc sudo from your initialisation files (~/.bash_profile, ~/.bashrc etc)

          Add the following lines to your initialisation files:



          if [ -f $(brew --prefix)/etc/bash_completion ]; then
          . $(brew --prefix)/etc/bash_completion
          fi

          # Your compspec here
          complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


          Reopen terminal.

          Type complete -p sudo.

          You should see complete -F _root_command sudo.



          Type complete -p salt.

          You should see something like this:



          complete -o default -o nospace -W 'a
          b
          c' salt


          bash-completion2.* note:

          You can install bash-completion2: https://github.com/Homebrew/homebrew/issues/19258

          But:





          • 2.* works with Bash 4.*


          • 2.* uses the -D option for compspecs lazy loading. So, complete -p sudo outputs complete: sudo: no completion specification until you type sudoSpaceTab






          share|improve this answer

































            -1














            sudo doesn't give you an login shell unless you ask for it with -i. So you'll find that without it you'll need to load the system's completions:



            . /etc/bash_completion


            If you run with -i, then $HOME will be ~root, and so anything written to the user's ~/.bashrc won't get read. If you can separate out the completion stuff from the rest of your ~/.bashrc, source that with . and that should work.






            share|improve this answer
























            • But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

              – G-Man
              Jun 27 '15 at 7:56











            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%2f141101%2fbash-does-not-autocomplete-my-command-when-using-sudo%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









            1














            Check set -o to see if maybe posix mode is enabled. If so, disable with set +o posix



            In "posix" mode, bash's tab-completion is for some reason disabled in "vi-mode". I've not seen any explanation why this behavior is so, nor why it's specific to vi-mode, so I didn't bother explaining.



            PS: This answer is more suited for someone who stumbles upon the question via a search engine... not for your particular setup.



            Update:

            Chet Ramey says:




            in POSIX mode, the vi editing mode should not map tab to complete.
            This is because POSIX.2 completely specifies the behavior of the vi
            editing mode, and the standard requires tab to be mapped to self
            insert by default.







            share|improve this answer





















            • 1





              Question about bash completion on posix mode

              – Evgeny Vereshchagin
              Jun 28 '15 at 3:01
















            1














            Check set -o to see if maybe posix mode is enabled. If so, disable with set +o posix



            In "posix" mode, bash's tab-completion is for some reason disabled in "vi-mode". I've not seen any explanation why this behavior is so, nor why it's specific to vi-mode, so I didn't bother explaining.



            PS: This answer is more suited for someone who stumbles upon the question via a search engine... not for your particular setup.



            Update:

            Chet Ramey says:




            in POSIX mode, the vi editing mode should not map tab to complete.
            This is because POSIX.2 completely specifies the behavior of the vi
            editing mode, and the standard requires tab to be mapped to self
            insert by default.







            share|improve this answer





















            • 1





              Question about bash completion on posix mode

              – Evgeny Vereshchagin
              Jun 28 '15 at 3:01














            1












            1








            1







            Check set -o to see if maybe posix mode is enabled. If so, disable with set +o posix



            In "posix" mode, bash's tab-completion is for some reason disabled in "vi-mode". I've not seen any explanation why this behavior is so, nor why it's specific to vi-mode, so I didn't bother explaining.



            PS: This answer is more suited for someone who stumbles upon the question via a search engine... not for your particular setup.



            Update:

            Chet Ramey says:




            in POSIX mode, the vi editing mode should not map tab to complete.
            This is because POSIX.2 completely specifies the behavior of the vi
            editing mode, and the standard requires tab to be mapped to self
            insert by default.







            share|improve this answer















            Check set -o to see if maybe posix mode is enabled. If so, disable with set +o posix



            In "posix" mode, bash's tab-completion is for some reason disabled in "vi-mode". I've not seen any explanation why this behavior is so, nor why it's specific to vi-mode, so I didn't bother explaining.



            PS: This answer is more suited for someone who stumbles upon the question via a search engine... not for your particular setup.



            Update:

            Chet Ramey says:




            in POSIX mode, the vi editing mode should not map tab to complete.
            This is because POSIX.2 completely specifies the behavior of the vi
            editing mode, and the standard requires tab to be mapped to self
            insert by default.








            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jun 28 '15 at 2:24









            hildred

            4,74622137




            4,74622137










            answered May 13 '15 at 0:02









            OtheusOtheus

            3,434932




            3,434932








            • 1





              Question about bash completion on posix mode

              – Evgeny Vereshchagin
              Jun 28 '15 at 3:01














            • 1





              Question about bash completion on posix mode

              – Evgeny Vereshchagin
              Jun 28 '15 at 3:01








            1




            1





            Question about bash completion on posix mode

            – Evgeny Vereshchagin
            Jun 28 '15 at 3:01





            Question about bash completion on posix mode

            – Evgeny Vereshchagin
            Jun 28 '15 at 3:01













            1














            Quick answer:




            • Install bash-completion

            • Source bash_completion on Bash startup

            • Add your compspec on Bash startup

            • Don't overwrite sudo compspec with complete -cf sudo


            I suppose that you use MacOSX with brew.



            Try:



            brew update
            brew install bash-completion
            brew info bash-completion
            # bash-completion: stable 1.3
            . $(brew --prefix)/etc/bash_completion
            complete -p sudo


            You should see something like this:



            complete -F _root_command sudo


            Test:



            function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
            complete -F _comp_foo foo


            Type foo SpaceTabTab

            You should see a b c



            Type sudo foo SpaceTabTab

            You should see a b c



            Then remove complete -fc sudo from your initialisation files (~/.bash_profile, ~/.bashrc etc)

            Add the following lines to your initialisation files:



            if [ -f $(brew --prefix)/etc/bash_completion ]; then
            . $(brew --prefix)/etc/bash_completion
            fi

            # Your compspec here
            complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


            Reopen terminal.

            Type complete -p sudo.

            You should see complete -F _root_command sudo.



            Type complete -p salt.

            You should see something like this:



            complete -o default -o nospace -W 'a
            b
            c' salt


            bash-completion2.* note:

            You can install bash-completion2: https://github.com/Homebrew/homebrew/issues/19258

            But:





            • 2.* works with Bash 4.*


            • 2.* uses the -D option for compspecs lazy loading. So, complete -p sudo outputs complete: sudo: no completion specification until you type sudoSpaceTab






            share|improve this answer






























              1














              Quick answer:




              • Install bash-completion

              • Source bash_completion on Bash startup

              • Add your compspec on Bash startup

              • Don't overwrite sudo compspec with complete -cf sudo


              I suppose that you use MacOSX with brew.



              Try:



              brew update
              brew install bash-completion
              brew info bash-completion
              # bash-completion: stable 1.3
              . $(brew --prefix)/etc/bash_completion
              complete -p sudo


              You should see something like this:



              complete -F _root_command sudo


              Test:



              function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
              complete -F _comp_foo foo


              Type foo SpaceTabTab

              You should see a b c



              Type sudo foo SpaceTabTab

              You should see a b c



              Then remove complete -fc sudo from your initialisation files (~/.bash_profile, ~/.bashrc etc)

              Add the following lines to your initialisation files:



              if [ -f $(brew --prefix)/etc/bash_completion ]; then
              . $(brew --prefix)/etc/bash_completion
              fi

              # Your compspec here
              complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


              Reopen terminal.

              Type complete -p sudo.

              You should see complete -F _root_command sudo.



              Type complete -p salt.

              You should see something like this:



              complete -o default -o nospace -W 'a
              b
              c' salt


              bash-completion2.* note:

              You can install bash-completion2: https://github.com/Homebrew/homebrew/issues/19258

              But:





              • 2.* works with Bash 4.*


              • 2.* uses the -D option for compspecs lazy loading. So, complete -p sudo outputs complete: sudo: no completion specification until you type sudoSpaceTab






              share|improve this answer




























                1












                1








                1







                Quick answer:




                • Install bash-completion

                • Source bash_completion on Bash startup

                • Add your compspec on Bash startup

                • Don't overwrite sudo compspec with complete -cf sudo


                I suppose that you use MacOSX with brew.



                Try:



                brew update
                brew install bash-completion
                brew info bash-completion
                # bash-completion: stable 1.3
                . $(brew --prefix)/etc/bash_completion
                complete -p sudo


                You should see something like this:



                complete -F _root_command sudo


                Test:



                function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
                complete -F _comp_foo foo


                Type foo SpaceTabTab

                You should see a b c



                Type sudo foo SpaceTabTab

                You should see a b c



                Then remove complete -fc sudo from your initialisation files (~/.bash_profile, ~/.bashrc etc)

                Add the following lines to your initialisation files:



                if [ -f $(brew --prefix)/etc/bash_completion ]; then
                . $(brew --prefix)/etc/bash_completion
                fi

                # Your compspec here
                complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


                Reopen terminal.

                Type complete -p sudo.

                You should see complete -F _root_command sudo.



                Type complete -p salt.

                You should see something like this:



                complete -o default -o nospace -W 'a
                b
                c' salt


                bash-completion2.* note:

                You can install bash-completion2: https://github.com/Homebrew/homebrew/issues/19258

                But:





                • 2.* works with Bash 4.*


                • 2.* uses the -D option for compspecs lazy loading. So, complete -p sudo outputs complete: sudo: no completion specification until you type sudoSpaceTab






                share|improve this answer















                Quick answer:




                • Install bash-completion

                • Source bash_completion on Bash startup

                • Add your compspec on Bash startup

                • Don't overwrite sudo compspec with complete -cf sudo


                I suppose that you use MacOSX with brew.



                Try:



                brew update
                brew install bash-completion
                brew info bash-completion
                # bash-completion: stable 1.3
                . $(brew --prefix)/etc/bash_completion
                complete -p sudo


                You should see something like this:



                complete -F _root_command sudo


                Test:



                function _comp_foo() { COMPREPLY=($(compgen -W 'a b c' -- "$2")); }
                complete -F _comp_foo foo


                Type foo SpaceTabTab

                You should see a b c



                Type sudo foo SpaceTabTab

                You should see a b c



                Then remove complete -fc sudo from your initialisation files (~/.bash_profile, ~/.bashrc etc)

                Add the following lines to your initialisation files:



                if [ -f $(brew --prefix)/etc/bash_completion ]; then
                . $(brew --prefix)/etc/bash_completion
                fi

                # Your compspec here
                complete -o default -o nospace -W "$(sudo ls -1 /var/cache/salt/master/minions)" salt


                Reopen terminal.

                Type complete -p sudo.

                You should see complete -F _root_command sudo.



                Type complete -p salt.

                You should see something like this:



                complete -o default -o nospace -W 'a
                b
                c' salt


                bash-completion2.* note:

                You can install bash-completion2: https://github.com/Homebrew/homebrew/issues/19258

                But:





                • 2.* works with Bash 4.*


                • 2.* uses the -D option for compspecs lazy loading. So, complete -p sudo outputs complete: sudo: no completion specification until you type sudoSpaceTab







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 31 at 15:44









                Stephen Kitt

                171k24386462




                171k24386462










                answered Jun 27 '15 at 8:14









                Evgeny VereshchaginEvgeny Vereshchagin

                3,30242236




                3,30242236























                    -1














                    sudo doesn't give you an login shell unless you ask for it with -i. So you'll find that without it you'll need to load the system's completions:



                    . /etc/bash_completion


                    If you run with -i, then $HOME will be ~root, and so anything written to the user's ~/.bashrc won't get read. If you can separate out the completion stuff from the rest of your ~/.bashrc, source that with . and that should work.






                    share|improve this answer
























                    • But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                      – G-Man
                      Jun 27 '15 at 7:56
















                    -1














                    sudo doesn't give you an login shell unless you ask for it with -i. So you'll find that without it you'll need to load the system's completions:



                    . /etc/bash_completion


                    If you run with -i, then $HOME will be ~root, and so anything written to the user's ~/.bashrc won't get read. If you can separate out the completion stuff from the rest of your ~/.bashrc, source that with . and that should work.






                    share|improve this answer
























                    • But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                      – G-Man
                      Jun 27 '15 at 7:56














                    -1












                    -1








                    -1







                    sudo doesn't give you an login shell unless you ask for it with -i. So you'll find that without it you'll need to load the system's completions:



                    . /etc/bash_completion


                    If you run with -i, then $HOME will be ~root, and so anything written to the user's ~/.bashrc won't get read. If you can separate out the completion stuff from the rest of your ~/.bashrc, source that with . and that should work.






                    share|improve this answer













                    sudo doesn't give you an login shell unless you ask for it with -i. So you'll find that without it you'll need to load the system's completions:



                    . /etc/bash_completion


                    If you run with -i, then $HOME will be ~root, and so anything written to the user's ~/.bashrc won't get read. If you can separate out the completion stuff from the rest of your ~/.bashrc, source that with . and that should work.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered May 4 '15 at 18:40









                    Toby SpeightToby Speight

                    5,30111031




                    5,30111031













                    • But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                      – G-Man
                      Jun 27 '15 at 7:56



















                    • But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                      – G-Man
                      Jun 27 '15 at 7:56

















                    But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                    – G-Man
                    Jun 27 '15 at 7:56





                    But this question is about somebody typing a sudo command into his default shell.  sudo hasn't started running yet, so its behavior is irrelevant; this is all about the behavior of the user's shell.

                    – G-Man
                    Jun 27 '15 at 7:56


















                    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%2f141101%2fbash-does-not-autocomplete-my-command-when-using-sudo%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 reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                    is 'sed' thread safe

                    How to make a Squid Proxy server?