27

Just about every time I 'cd' to a different directory on my machine (in this case, running Mac OS X 10.6.7) via the command line (which is bash), I immediately type 'ls' to get the list of contents in that directory. I'm trying to figure out a way to override 'cd' so that it changes to the requested directory and then gives me the list in one shot.

I've been able to get the basic functionality I'm looking for working by with the following line added to my ~/.bash_profile

function cl() { cd "$@"; ls -l; }

This works as expected. Changing to the requested directory and then showing me the contents. Where I run into an issue is trying to override "cd" itself instead of creating a new "cl" command.

The following things do not work

##### Attempt 1 #####
# Hangs the command line

function cd() { cd "$@"; ls -l; }


##### Attempt 2 #####
# Hangs the command line

function cd() { 'cd' "$@"; ls -l; }


##### Attempt 3 #####
# Does not change directory. 
# Does list contents, but of the directory where you started.

function cd() { /usr/bin/cd "$@"; ls -l; }


#### Other attempts that fail in various ways #####
alias cd=cd "$@"; ls -la;
alias cd="cd '$@'; ls -la;"
alias cd='cd "$@"'; ls -la;
alias cd=/usr/bin/cd "$@"; ls -la;

I also tried several other iterations that aren't listed as well as making an alias that points to the working 'cl' function. None of which worked.

What I've read in documentation talks about the fact that 'cd' can't be run as an external command (which is what I understand to be the way the function would need to use it).

So, I can currently use my "cl" command and get what I want, but the question is/remains:

Is there a way to override the behavior of 'cd' to have it change to the requested directory and then do something else afterward?

gparyani
  • 1,881

3 Answers3

37

The following should work:

function cd() { builtin cd "$@" && ls -l; }

Since the function is on a single line, ensure that it is terminated with ; as above in order to work correctly.

Gareth
  • 19,080
12

I think you're running into a loop. Your cd function is calling cd, which is... the function.

You need to know about builtin which is a keyword which makes command lookup use the the Bash builtins like cd and not your function

function cd
{
    builtin cd "$1"
    : do something else
}

Also, calling /usr/bin/cd will never work, even if such a command existed.

What would happen:

  • My Bash shell is in dir /bash/dir.
  • I run a command /usr/bin/cd /dir/for/cd.
  • /usr/bin/cd goes to dir /dir/for/cd.
  • /usr/bin/cd exits.
  • Bash is still in /bash/dir, because the child process /usr/bin/cd can not affect the parent.

Also aliases are simple text substitutions. They can never have parameters.

Giacomo1968
  • 58,727
Rich Homolka
  • 32,350
6

I suggest not to override the cd because there are some other scripts hijacking the 'cd' function, for example, rvm. It would be better to choose another name, like 'd', instead and don't specify the 'builtin' type in your function; otherwise, the hijacker would not function. I am using the code below:

function d() { cd "$@" && ls;} 
Wen
  • 161
  • 1
  • 3