How can I expand a relative path at the command line, with tab completion?

7,860

Solution 1

I can't find a good way to do that.

What I do is type $PWD before the file name, then press Tab to expand it. In bash you may need to press Ctrl+Alt+e instead of Tab.

e.g.

vi $PWD/000-default

then

Ctrl+Alt+e

then

Enter

Solution 2

You could use programmable tab completion within bash for this:

function _vim_complete_file() {
    IFS=$'\n' read -d '' -a FILES <<< "$( compgen -A file "${COMP_WORDS[$COMP_CWORD]}" )"
    IFS=$'\n' read -d '' -a COMPREPLY <<< "$( realpath "${FILES[@]}" )"
}

complete -F _vim_complete_file vim

Now if you type vim 000TAB, it will replace 000 with /path/to/000-default.

Explanation
The way this works is that complete -F _vim_complete_file vim tells bash to use the function _vim_complete_file whenever you press TAB on an argument to vim.
The function then runs compgen -A file on the current word the cursor was on when you hit TAB. This returns a list of files matching it.
That list of files is then passed to realpath which generates the fully qualified path. This list is stored as an array in COMPREPLY which the shell looks in for the available completions.

Solution 3

You might want to start using pushd and popd so it's easier to go back to a previous directory: http://gnu.org/software/bash/manual/bashref.html#The-Directory-Stack

I saw your comment about cdargs (which I assume is this). For directories that I use frequently, I use an alias or function. For example

alias cgi='pushd /path/to/apache/cgi-bin'

or

docs() { pushd /path/to/apache/docroot/"$1"; }

The 2nd form is useful if there's a parent directory where the subdirs are frequent, then docs foo takes me to /path/to/apache/docroot/foo. The downside is you lose tab completion, but it hasn't been so arduous for me.

Solution 4

If you are re-editing in Vim, check out :browse oldfiles and :help oldfiles.

Share:
7,860
cwd
Author by

cwd

Updated on September 18, 2022

Comments

  • cwd
    cwd over 1 year

    In bash is there any way to expand a relative path into an absolute path, perhaps with tab completion?

    I ask because sometimes I will search for a file, find it, then vim it:

    cd /etc
    cd apache2
    cd sites-available
    vim 000-default
    

    Then I will do some other things and change directories:

    cd /tmp
    ls
    cd ~
    ls
    

    Then I'll find that I need to edit the same file again, but it is not possible to use history, (or history search), because the file path is relative.

    Current Workaround

    If I know I'm going to be reusing a file a lot, after I find it I will grab the full path using something like realpath:

    $ realpath 000-default
    /etc/apache2/sites-available/000-default
    (copy and paste path into next command:)
    $ vi /etc/apache2/sites-available/000-default
    

    Caveats

    This still requires copying and pasting. I believe there should be an easier way to get a file's full path into my history. What options do I have?

    I believe that I have (accidentally) pressed some key combination before that expanded a relative path into a full path. I know in bash you can type:

    cd /etc
    ls bash_*(control+x *)
    

    and get:

    ls bash.bashrc bash_completion bash_completion.d
    

    So is there a way I can expand a relative path into an absolute path, so that I can save operations on a file in my history with that file's full path?

    • Angel Todorov
      Angel Todorov about 12 years
      You might want to start using pushd and popd so it's easier to go back to a previous directory: gnu.org/software/bash/manual/bashref.html#The-Directory-Stac‌​k
    • cwd
      cwd about 12 years
      @glennjackman - that looks really good. I found this blog and the comments really helpful, too. I'm also looking into cdargs now. Thanks! ps: if nobody else has a better answer just post that and I will accept it.
    • phemmer
      phemmer about 12 years
      Another possible solution is to leave vim running while youre working around with files, and then bring it back up. You can do this by either doing :sh in vim to start a subshell, and then exit or CTRL+D to get back into vim. Or by doing CTRL+Z in vim to background (STOP) it and then fg to get it back.
    • Gilles 'SO- stop being evil'
      Gilles 'SO- stop being evil' about 12 years
  • cwd
    cwd about 12 years
    damn. this is EXACTLY what I wanted to do. so simple! tab worked for me although ctrl+alt+e did not. I'm using a mac and iTerm2 to ssh to ubuntu. any way to set up something easier than $PWD? (the all caps is kind of cumbersome)
  • cwd
    cwd about 11 years
    update: on mac OS X I realized I can press escape, then control+e to expand the current line even if bash's tab expansion is not enabled.
  • Mikel
    Mikel about 11 years
    Right. Esc+Ctrl+e is equivalent to Ctrl+Alt+e. Esc sometimes works when Alt (or I guess Option on Mac?) doesn't.
  • jthill
    jthill almost 4 years
    Also the number marks, '0 etc.