How do I get bash to respect my physical directory structure? (And likewise for Emacs?)

4

If in bash, I do "set -P" then bash follows the "physical directory structure" when doing "pwd" and "cd .." etc, rather than the "logical one" that might be defined via symlinks. Unfortunately, bash still doesn't obey the physical directory structure for filename completion. How can I get bash to respect my authority on this issue?

Thanks!
|>ouglas

P.S. Unfortunately, the same problem has now afflicted Emacs for opening files, etc. If anyone also knows how to also tell Emacs to respect my physical directory structure, then I'd also like to know the answer to that.

P.P.S. I don't know who decided that having some programs try to fathom your "logical directory structure" was a good idea, but it's not! Not unless you can convince every program in the world to do things this way, since having some programs use your physical directory structure, and having other ones use your logical directory structure is a recipe for confusion and annoyance.

Douglas

Posted 2010-01-05T21:33:20.447

Reputation: 171

I don't understand the problem. Are you not able to open files? Is bash completion getting the wrong path? – James Polley – 2010-01-05T23:21:47.793

That depends on what you mean by "wrong". Bash is not following the Unix meaning of "..", which is a real directory entry in a directory, and points to the physical parent directory. Instead bash is interpreting ".." to mean "strip one entry off the path that I took to get here".

I don't want to use this fancy newfangled meaning. I want the normal Unix meaning. – Douglas – 2010-01-06T19:42:30.907

Answers

3

Thanks for the previous answers. But, actually, as it turns out, "set -P" does the job just fine all by itself, contra my original query on the issue.

When I was originally trying this out, I must have somehow gotten bash into a confused state where filename completion wasn't respecting the "set -P" setting. But now with a fresh bash, it's all working fine. "set -P" seems to put bash into "physical directory structure" mode consistently throughout bash.

Douglas

Posted 2010-01-05T21:33:20.447

Reputation: 171

1

This might get you part of the way there.

Use type -a _expand and compare its output to the function below. The existing function should match the part that's after the first else below. If not, you can wrap what you have in the outer if...else as you see it here.

Paste it at a Bash prompt to test. Then, if you're satisfied, put it in your ~/.bashrc file to override the function definition in /etc/bash_completion (instead of editing it directly).

_expand ()
{
    if [[ $- == *P* && -L "$cur" && -d "$cur" ]]; then
        cd "$cur";
        eval cur="$PWD";
        cd - > /dev/null;
    else
        if [[ "$cur" == \~*/* ]]; then
            eval cur=$cur;
        else
            if [[ "$cur" == \~* ]]; then
                cur=${cur#\~};
                COMPREPLY=($( compgen -P '~' -u $cur ));
                [ ${#COMPREPLY[@]} -eq 1 ] && eval COMPREPLY[0]=${COMPREPLY[0]};
                return ${#COMPREPLY[@]};
            fi;
        fi;
    fi
}

This is piggy-backing on the tilde-expansion function of Bash's tab completion.

Now you can do

ls -l symdir<TAB>

and you'll see

ls -l /dest/dir<CURSOR>

Paused until further notice.

Posted 2010-01-05T21:33:20.447

Reputation: 86 075