3

I want to write an alias command for 'ls', so that if I pass in a parameter, then the alias will use it, but if I do not, then it would use '*' instead. This is the alias I have today:

alias lsd='ls --color -lh | grep "^d" && ls --color -lh | grep -v "^d"

My problem is that no matter what I type for the lsd command, I always get all files in the response. So, when I type lsd *.sh, I still get all directories and files in the listing.

I copied this alias from another SuperUser post but don't really understand it yet.

Thanks for any help.

UPDATE: Ok, now I have this function defined in my .bashrc file:

function lsd() {
  if [[ -z $1 ]] ; then
    command ls --color -lh | grep "^d" && ls --color -lh | grep -v "^d"
  else
    command ls --color -lh "$1" | grep "^d" && ls --color -lh "$1" | grep -v "^d"
  fi
}

When I run that with just lsd, it works as I want. When I run it with lsd *.wav though, I still get the directory names in the output and then I see "Binary file x.wav matches output". What am I doing wrong?

In case it's not clear, I am trying to list directories and then files, but only those matching the first parameter in the command. So when I enter lsd *.wav, I don't expect to see directories since their names don't end with .wav. Thanks for all the help! :)

LAST: Never mind. I was using source .bashrc to try to update bash but that wasn't working so the old commands were still running. I closed my ssh session and logged back in and this new command is working now. Thanks all!

0

4 Answers 4

4

Aliases do not take parameters. Use alias if you only want to replace a long string by a short one. For parameter processing, use a function:

ls () {
    if [[ -z $1 ]] ; then
        command ls *
    else
        command ls "$@"
    fi
}
7
  • 2 things: use [[ -z $1 ]] otherwise you might be providing too many arguments (try this: [[ -z a b c ]]); use command ls not 'ls' Jan 20, 2014 at 21:20
  • I'm confused now. Is what Slowki is telling me wrong then? He seems to be suggesting I can use a parameter in my alias command. Thanks.
    – Peter
    Jan 20, 2014 at 21:44
  • @glennjackman: thanks. Any details on the difference between 'ls' and command ls?
    – choroba
    Jan 20, 2014 at 21:49
  • Choroba, I think this page answers your last question - ss64.com/bash/command.html. "Only shell built-in commands or commands found by searching the PATH are executed. If there is a shell function named ls, running `command ls' within the function will execute the external command ls instead of calling the function recursively."
    – Peter
    Jan 20, 2014 at 22:16
  • @Peter: That's what quoting 'ls' does, too.
    – choroba
    Jan 20, 2014 at 22:19
1

Use -z to check if the variable isn't set.

alias ls='[ -z $1 ] && ls * || ls $*'
4
  • Sorry, I just re-wrote my question since you answered the first version. Does this still make sense, with my new question? Thanks for the help.
    – Peter
    Jan 20, 2014 at 20:46
  • My answer was just an example to show checking for a variable, it should be easy to adapt to your needs basically all you need to do is [ -z $1 ] && IfThereIsNoVariable || IfThereIsAVariable so after the && would go the command for when you just ran lsd and after the || would go the command if you ran lsd *.sh
    – user270595
    Jan 20, 2014 at 21:10
  • thanks. So, just so I'm clear, is -z a part of the ls command, or something defined for alias, or is it a part of bash?
    – Peter
    Jan 20, 2014 at 21:43
  • It's part of bash, [ -z $1 ] is a shell scripting if statement. but now that I think about it, you'd need to make it into a different script, then alias to that script. ex. alias lsd='Path/To/Script' then put [ -z $1 ] && LsWithoutArguement || LsWithArguement inside Path/To/Script
    – user270595
    Jan 20, 2014 at 22:41
0

As others have said, "alias" doesn't process the command line arguments given on the command line that invokes the "aliased" command. It simply passes along all the command line arguments to the substituted command by appending the arguments to the end.

Here is an example test script to show this effect...

Start with a script like this:

[~]# cat /some...path/ls1.sh
#!/bin/sh

dollarpound="$1"
shift
dollarone="$1"
shift

echo ""
echo "dollarpound=\"$dollarpound\""
echo "dollarone=\"$dollarone\""
echo "\$*=\"$*\""
echo "\$@=\"$@\""
echo "\$1=\"$1\""
echo "\$2=\"$2\""
echo ""

if [ $# -eq 0 ]; then
  echo ls --color -lh *
else
  echo "ls --color -lh $*"
fi
echo ""
[~]#

Then, assign that script to an alias:

[~]#alias lsx='/some...path/ls1.sh $# "$1"'
[~]#

Invoke the alias lsx with no arguments:

[~]# lsx

dollarpound="0"
dollarone=""
$*=""
$@=""
$1=""
$2=""

ls --color -lh ant bat cat dog eel.txt fox.txt goat.jpg horse.jpg

[~]#

Invoke the alias lsx with 1 argument: "*.txt":

[~]# lsx *.txt

dollarpound="0"
dollarone=""
$*="eel.txt fox.txt"
$@="eel.txt fox.txt"
$1="eel.txt"
$2="fox.txt"

ls --color -lh eel.txt fox.txt

[~]#

Notice that the script invoked by the "aliased" command reports 0 arguments instead of 1 ("*.txt"), or 2 ("eel.txt", "fox.txt").

Invoke the alias lsx with 4 arguments:

[~]# lsx ant bat cat dog

dollarpound="0"
dollarone=""
$*="ant bat cat dog"
$@="ant bat cat dog"
$1="ant"
$2="bat"

ls --color -lh ant bat cat dog

[~]#

Notice that the script invoked by the "aliased" command reports 0 arguments instead of 4.



So, a working version of the script is:

[~]# cat /some...path/ls2.sh
#!/bin/sh

if [ $# -eq 0 ]; then
  \ls --color -lh *
else
  \ls --color -lh $*
fi
[~]#

(Notice the \ before ls. This prevents ls from being further substituted by other "aliases", etc...).

Assign the working script to an alias:

# alias lsx='/some...path/ls2.sh'
[~]#

Invoke the alias lsx with no arguments:

[~]# lsx
-rw-r--r-- 1 someuser someuser    0 Jan 21 02:42 eel.txt
-rw-r--r-- 1 someuser someuser    0 Jan 21 02:42 fox.txt
-rw-r--r-- 1 someuser someuser    0 Jan 21 02:42 goat.jpg
-rw-r--r-- 1 someuser someuser    0 Jan 21 02:42 horse.jpg

ant:
total 0

bat:
total 0

cat:
total 0

dog:
total 0
[~]

Notice that the script detected there were no arguments and ran "ls *" instead of "ls" (with no arguments).

Invoke the alias lsx with 1 argument: "*.txt":

[~]# lsx *.txt
-rw-r--r-- 1 someuser someuser 0 Jan 21 02:42 eel.txt
-rw-r--r-- 1 someuser someuser 0 Jan 21 02:42 fox.txt
[~]

Invoke the alias lsx with 4 arguments:

[~]# lsx ant bat cat dog
ant:
total 0

bat:
total 0

cat:
total 0

dog:
total 0
[~]#

If there is a reason you want to do this with an "alias", this should work for you. Just just give the alias and the script whatever names you like. For example, if you wanted to "alias" the ls command, use alias ls='/some...path/ls2.sh' (with the path and name you used for the script).

On the other hand, if you want this command to be uniquely named, like lsx for example, it might be simpler to just give the script that name, and put the script in a folder that is included in the path, like: /bin/lsx, or whatever you like.

0

I wanted to alias a command, so I could do something different when it's run.

For example, I wanted to have it so

$ git push

did some other things first, before pushing. I know I could probably handle this in a git way, but this is a general solution to the problem of wanting to alias a command and it's arguments.

I created an alias like so, that points to a bash script:

$ alias git="$HOME/bin/git"

I then created a bash script to intercept certain git calls

~/bin/git

#!/usr/bin/env bash

# avoid recursive calls to this bash script
if [ "$IN_GIT_BIN" != "true" ]; then

  # intercept calls to "git push", and do something 
  if [ "$1" == "push" ]; then
    shift;
    echo "using ~/bin/git ...."
    IN_GIT_BIN="true" do_extra_things "$@"
    exit;
  fi
fi

# if not intercepted, run original git command
/usr/local/bin/git "$@"

This allows me to have other scripts that use git in them, and they wont use my git override, they'll use the original binary of git instead.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .