Search code examples
linuxperlaliastcsh

Properly quoting a tcsh alias using backticks


I'm using tcsh. I'd like to alias "cdup" to cd up to a directory one level down from a reference directory. For example, if my reference directory is /home/myself/support/bugs/, and I'm in /home/myself/support/bugs/bug1/foo/bar, I'd like cdup to change directory to /home/myself/support/bugs/bug1. I tried the following:

alias cdup 'cd `perl -e \'print $1 if $ENV{PWD} =~ m#\(/home/myself/support/bugs/[^/]+\)#\'`'

but I get:

Unmatched `.


Solution

  • Some of that quoting is unnecessary, what makes this far easier

    alias cdup cd `perl -e'print $1 if $ENV{PWD} =~ m{(/home/user/support/bugs/[^/]+)}'`
    

    Or you can break up the job and avoid quoting issues

    set d=`perl -e'print $1 if $ENV{PWD} =~ m{(...)}'`; alias cdup $d; unset d
    

    These both do the same, in tcsh.

    However, if pwd is not within that "reference directory" then the alias ends up being cd, what puts you back into the home directory. This is how the question is posed -- but is that really desired?

    One way to remedy this in the first approach above is to set the directory to the current directory itself if we are outside of the reference hierarchy

    alias cdup cd `perl -e'$ENV{PWD} =~ m{(...)}; print $1 // $ENV{PWD}'`
    

    Here // is the defined-or operator.

    Or it may be more suitable to avoid setting the alias altogether when outside the reference hierarchy, but then that need be done in tcsh

    set d=`perl -e'print $ENV{PWD} =~ m{(...)}'`; if ($d != "") alias cdup cd $d ; unset d
    

    Because of the capturing () in regex the match operator in list context (imposed by print) returns its capture or undef (if it didn't match), so shell's variable $d ends up being either the captured value or an empty string.

    Then the alias is set conditionally -- so there is no cdup if there was no match.


    From tcsh manual

    alias [name [wordlist]]
    Without arguments, prints all aliases. With name, prints the alias for name. With name and wordlist, assigns wordlist as the alias of name. wordlist is command and filename substituted. name may not be 'alias' or 'unalias'. See also the unalias builtin command.

    Note no mention of quotes, which are not needed for the wordlist