I find that I often do the following:

%> cd bla/bla
%> ls

I would like it that whenever I cd into a directory it automatically does an ls.

I fiddled with my .bashrc for a while, but couldn't figure out how to make it happen.

12 Answers 12


You can do this with a function:

$ cdls() { cd "$@" && ls; }

The && means 'cd to a directory, and if successful (e.g. the directory exists), run ls'. Using the && operator is better than using a semicolon ; operator in between the two commands, as with { cd "$@"; ls; }. This second command will run ls regardless if the cd worked or not. If the cd failed, ls will print the contents of your current directory, which will be confusing for the user. As a best practice, use && and not ;.

$ cdls /var/log
CDIS.custom     fsck_hfs.log    monthly.out     system.log
$ pwd

In general, it is a bad practice to rename a command which already exists, especially for a commonly called command like cd. Instead, create a new command with a different name. If you overwrite cd with a function or alias which is also named cd, what would happen when you enter a directory with 100,000 files? There are many utilities that use cd, and they may get confused by this unusual behavior. If you use a shared account (Such as root when you are working with other system administrators), it can be very dangerous to replace an existing command because the environment is different from what people expect.

  • That command really change directory? From bash's man page: "There is no mechanism for using arguments in the replacement text. If arguments are needed, a shell function should be used" – enzotib Sep 9 '11 at 18:58
  • 2
    First: it does not work here. Second: in that page they use variables, not positional parameters. Third: ABS is a common source of bad practices. – enzotib Sep 9 '11 at 19:07
  • 1
    The alias works for me on Snow Leopard but not on CentOS5 or CentOS6. I updated my answer to use a function only. No aliases. – Stefan Lasiewski Sep 10 '11 at 0:37
  • 1
    Does not work for me. Tried @frabjous answer and it works: cd() { builtin cd "$@" && pwd; }; -- using standard bourne shell on macOS (Sierra 10.12.6) – Swivel Sep 30 '17 at 19:10
  • 1
    i mean i'd rather have it override cd for the 100,000 different times i have to use it, rather than the one folder I could potentially come across with 100,000 files. Having to type cdls defeats the point and might as well just do the two commands but that's just me – Emobe Sep 17 '19 at 11:00

I have this in my .bashrc, and it works fine.

function cd {
    builtin cd "$@" && ls -F

Earlier in my .bashrc I have: [ -z "$PS1" ] && return, and everything after that line only applies to interactive sessions, so this doesn't affect how cd behaves in scripts.

  • 1
    What exactly does [ -z "$PS1" ] && return do? – syntagma Jan 21 '15 at 14:34
  • 2
    [ -z "$PS1" ] checks if the $PS (interactive prompt variable) is "zero length" (-z). If it is zero length, this means it has not been set, so Bash must not be running in interactive mode. The && return part exits from sourcing .bashrc at this point, under these conditions. – frabjous Jan 21 '15 at 17:42
  • 2
    Another way to check for interactivity is to look for i in "$-": case "$-" in *i*) ;; *) return ;; esac. – Kusalananda Jan 9 '17 at 19:38
  • 3
    @Swivel The PS1 variable may be unset or empty and the shell may still be interactive (but without a prompt). I would check $- to make sure. – Kusalananda Sep 30 '17 at 19:24
  • 1
    @Swivel There shouldn't be a reason to export PS1. – Kusalananda Sep 30 '17 at 19:48

off-topic, since the question is tagged /bash, but as some questions are closed as duplicate of this one that don't mention bash:

With zsh:

chpwd() ls

The chpwd() function is called by zsh whenever the current directory changes (by way of cd, pushd, popd...). tcsh has a similar feature and is probably where zsh got it from.


Why not add an alias to your .bashrc file?

Something like:

alias cdls='cd "$@" && ls'
  • @don_crissti A funtion and an alias are different things. So why not? – Jodka Lemon Dec 16 '15 at 14:09
  • This is the quickest and cleanest way of doing what the OP asked for. In my opinion, functions should be used for more complicated things, while making shortcuts for often typed commands are exactly what aliases exist for. – Ghos3t Feb 22 '19 at 1:27
  • 2
    I am having a strange issue with this alias, when I use it like this, cdls projec2, it will show all the files in the project 2 folder but not actually cd to that folder, instead, it will remain in the original folder. – Ghos3t Feb 28 '19 at 23:18
  • Yep, using an alias simply lists contents in that directory, but doesn't actually cd to there. – a3y3 Nov 9 '19 at 16:54

The common solution of creating alias for cd command is not perfect because there are other commands which can change your current directory like popd or even running a script with cd command in it.

It is better to use $PROMPT_COMMAND Bash hook which executes a command before returning a prompt.

The command (a function in our case) will execute ls only if directory has changed to reduce screen noise. Code for .bashrc:

    #each console has its own file to save PWD
    #don't ls when shell launched
    echo $PWD > $PrevDir
    LsAfterCd() {
        [[ "$(< $PrevDir)" == "$PWD" ]] && return 0

        ll --color=always | sed 1d

        echo $PWD > $PrevDir
  • I found that setting a variable in LsAfterCd will inject it into the current bash session. Using a variable to keep the directory allows this to be simplified. – Roger Dahl Jan 13 at 7:52
  • By "simplified" do you mean "get rid of the PrevDir file"? – Jack Jan 14 at 15:45

Copy this:

altercd(){ cd(){ unset -f cd ; cd $*; ls ; altercd; } } ; altercd 

Now you just can do simple cd:

cd / 
(files listed)
cd /home 
(files listed)

In bash you cannot recur to aliases for action that require parameter. For this there are functions. So put in your ~/.bashrc the following

mycd() {
  cd "$1"
  • 5
  • To allow a parameter for the ls command, I use function mycd { builtin cd $1 && ls $2 }. Now you can call the command e.g. mycd .. -la – Christian Schulzendorff Feb 19 '16 at 9:20
  • @ChristianSchulzendorff: better to use the quotes: function mycd { builtin cd "$1" && ls "$2" } . – enzotib Feb 19 '16 at 16:58
  • Does not work, I just tried it. The file was empty, but after adding your code, nothing changed. – Black Jun 25 '18 at 14:20

Even more handy - with ability to go back in history:

function cd() {
    if [ -d "$@" ]; then
        echo -n "Stack: "
        pushd "$@"
        builtin cd "$@"
function popd() {
    builtin popd "$@" && ls

When you change directory a line with: Stack: (current_dir) (previous_dir) ... will be shown, then ls output. To go back in dirs history just pop this command: popd.

I added else so you'll see an error when trying to go to a wrong directory.

  • 1
    if you just do cd - it will bring you to your last dir that you were in. – Ian Nov 13 '17 at 12:25

Place the below code in the .profile and it works. Tested on HP-Unix box.

if [ "$#" = 0 ]; then
cd ~ && ls -ltr
elif [ -d "$@" ]; then
cd "$@" && ls -ltr
echo "$@" directory not found!!!

alias cd="cdl"

I think it's good to enable ls's options in this way as cd takes no option.

cdls() {
  cd ${$#} && ls ${@:0:$#-1}
  • Umm... cd does take options. – Kusalananda Jan 11 '19 at 19:20

Here's what I find useful (on Debian 9):

c() {
    cd "${@}" \
    && ls --color=always -C \
    | sed '
        # on line 5, print the line,
        5 {
            # append an ellipsis
            # and quit
        # print lines 1-4 verbatim

This gives me truncated output with an ellipsis in case there are too many items in that directory so that the console stays clean:

$ c data/git/buildroot/package/
4th                              lua-markdown
a10disp                          lua-messagepack
acl                              lua-msgpack-native
acpica                           luaossl
acpid                            lua-periphery
$ ls -1 | wc --lines
alias cd='builtin cd $1 && ls -l && builtin cd $1'
  • This add nothing that the other answers have not already covered. – jasonwryan Jul 17 '16 at 3:58

Not the answer you're looking for? Browse other questions tagged or ask your own question.