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.
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.
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
/var/log
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.
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.
[ -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
i
in "$-"
: case "$-" in *i*) ;; *) return ;; esac
.
– Kusalananda
Jan 09 '17 at 19:38
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
$-
. Thanks a lot :D
– Swivel
Sep 30 '17 at 19:38
.bashrc
and noticed the custom prompt I wrote. Completely invalidates [ -z "$PS1" ]
. For those who also export their own custom prompts, remember this! If you must use $PS1
for checking for interactive shell, remember to place your export PS1
after the check!
– Swivel
Sep 30 '17 at 19:40
~/.bashrc
. It'll be hidden since it starts with a period. If it doesn't exist, you can create it. That's a pretty elementary point, so you might want to read a basic bash tutorial before implementing suggestions like these.
– frabjous
Jun 26 '18 at 14:44
builtin cd "$@" && ls -la | head -n $(tput lines)
– Slawa
Jul 03 '20 at 10:23
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... see also the autocd
feature). tcsh has a similar feature and is probably where zsh got it from.
In newer versions of zsh
, like for other hook functions, you can do:
my_chpwd_hook() ls
chpwd_functions+=( my_chpwd_hook )
That approach would be preferable if you or some third-party plugin you use have separate and independent things to do when the current working directory changes.
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
PrevDir=$(tty)
PrevDir=/tmp/prev-dir${PrevDir////-}
#don't ls when shell launched
echo $PWD > $PrevDir
LsAfterCd() {
[[ "$(< $PrevDir)" == "$PWD" ]] && return 0
ll --color=always | sed 1d
echo $PWD > $PrevDir
}
PROMPT_COMMAND=LsAfterCd
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 '21 at 07:52
Why not add an alias to your .bashrc file?
Something like:
alias cdls='cd "$@" && ls'
$@
like functions do. This alias uses the list of positional parameters from the current shell as the arguments for cd
, if there are any (if there are none, it will cd
to the user's home directory), and it the executes ls
with whatever arguments are following the alias on the command line.
– Kusalananda
Jan 12 '23 at 18:00
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"
ls
}
function mycd { builtin cd "$1" && ls "$2" }
.
– enzotib
Feb 19 '16 at 16:58
An alias would be intuitive, but aliasses might not work as you expect.
An alias like this
alias mycd='cd "$1" && ls'
is effectively
alias mycd='ls'
You cannot put a (positional) parameter "into" an alias definition like "$1"
for cd
.
Try a command line input
cd "$1"
and see that it exactly does: nothing - because it is just
cd ""
It would be nice if cd
did throw an error here complaining about no or illegal arg, but it does just nothing.
An alias is not a function where you can give parameters that are placed by your definition inside the function. With an alias the parameters stay where they are: at the end of your code, so with the initially defined mycd
alias the command
mycd bla/bla
would just be a shortcut for
cd "" && ls bla/bla
being effetctively
ls bla/bla
So you indeed need a function like
mycd() { cd "$1" && ls ; }
that you could just type in at command line like an alias definition to become a part of your environment like an alias - with Bash / shell scripting you don't need a script to call a function, just type "mycd xy" at command line.
Dont't forget that in a one-liner function definition you need the semicolon before the "}" and mind the spaces around the curlies), but of course you may define it like
mycd() {
cd "$1" && ls
}
even at command line if you are more comfort with that (Bash will recognize by "{" that you are not finished and will show the PS2 prompt on return key for further commands before, by "}", your input will be executed, signalized by PS1 prompt after execution).
Of course you know that using parens "()" for function bodies makes them "real" functions without side effects, but here you want the side effect of
cd
'ing to another dir - a real function wouldcd
inside a subshell, do stuff there, and then return, explicitly without changing caller's environment of which the current directory ("cd") is a property. Note that this has nothing to do with the "alias problem" stated above, although effects might look similar.
As like aliasses you have to put the function definition in one of the initialization scripts ~/.bash_profile
, ~/.bash_login
, or ~/.profile
to provide it for every (sub)shell your are opening.
cd
with no argument, is not the same as cd
with an empty argument. Neither is "illegal" and both have their uses. Also note that if $1
is set, then the faulty alias would definitely be doing something other than just listing the named directory/file. You can also call you shell function cd
if you call cd
as command cd
inside the function.
– Kusalananda
Dec 19 '21 at 16:15
readonly -f
works on functions in bash
. See help readonly
and the manual. Also, I have not seen standard utilities say things about "no args" or "illegal args".
– Kusalananda
Dec 19 '21 at 17:25
Place the below code in the .profile and it works. Tested on HP-Unix box.
cdl()
{
if [ "$#" = 0 ]; then
cd ~ && ls -ltr
elif [ -d "$@" ]; then
cd "$@" && ls -ltr
else
echo "$@" directory not found!!!
fi
}
#SET YOUR ALIAS TO CD
alias cd="cdl"
Even more handy - with ability to go back in history:
function cd() {
if [ -d "$@" ]; then
echo -n "Stack: "
pushd "$@"
ls
else
builtin cd "$@"
fi
}
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.
I think it's good to enable ls
's options in this way as cd
takes no option.
cdls() {
cd ${$#} && ls ${@:0:$#-1}
}
cd
does take options. Additionally, your function can't be used on directories containing spaces, tabs, or newlines in their names.
– 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
a[...]
# and quit
q
}
# 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
1977
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)
etc...
cd
to call the actual, built-in “change directory” directive rather than calling itself recursively — which you could have more easily accomplished with cd() { builtin cd $*; ls; }
. … (Cont’d)
– G-Man Says 'Reinstate Monica'
Dec 21 '21 at 19:29
builtin cd
; i.e., the first version of your answer was, essentially, a flawed copy of frabjous’s answer (flawed in that it used $*
instead of "$@"
), but then you rewrote it to be what it is now in an attempt to be POSIX-compliant (because POSIX doesn’t support the builtin
command). … (Cont’d)
– G-Man Says 'Reinstate Monica'
Dec 21 '21 at 19:30
builtin cd
to be POSIX-compliant. Which leaves me wondering why you deleted the explanation. … … … … … … … … … … … … … … … … … … P.S. I’m not 100% sure, but I believe that command cd
would work, and it is POSIX-compliant.
– G-Man Says 'Reinstate Monica'
Dec 21 '21 at 19:30
builtin cd
, and then 35 minutes later you posted the first altercd
version, announcing that it was POSIX compatible.
– G-Man Says 'Reinstate Monica'
Dec 24 '21 at 01:36
No need to create functions altering the actual command. Its better to write this way in one line:
cd /myfolder; ls;
This will do the job as it executes 2 commands, one after the other in a single line.
;
to &&
you could possibly justify this answer more easily. But even so it doesn't seem like it would do what the asker wants
– Chris Davies
May 20 '23 at 08:25
pwd
. Not sure if this is a best practice, but it is commonly done. See http://tldp.org/LDP/abs/html/aliases.html for some examples. – Stefan Lasiewski Sep 09 '11 at 19:05$1
will remain in the alias expansion. – Gilles 'SO- stop being evil' Sep 09 '11 at 23:38cdl
, since the point is to save typing. – Keith Thompson Jul 01 '13 at 19:55cd() { builtin cd "$@" && pwd; };
-- using standard bourne shell on macOS (Sierra 10.12.6) – Swivel Sep 30 '17 at 19:10cd
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 typecdls
defeats the point and might as well just do the two commands but that's just me – Emobe Sep 17 '19 at 11:00c
. That doesn't defeat the point anymore - of having to typels
anyway. – Daniel Katz Aug 26 '21 at 11:50