0

I need to do this as an alias - if possible

alias d='pushd +$1'

This won't work for some reason, because when I execute the alias it gives me this:

d 3

-bash: pushd: +: invalid number
pushd: usage: pushd [-n] [+N | -N | dir]

but this will work

~ $alias d='pushd +3'
~ $d
/Library/Java/JavaVirtualMachines $

There is something about having the plus symbol next to the argument variable that isn't working and I don't know why.

Is there a way to make this work?

Thank you,

Mike

Edit: This is for the discussion happening below:

~ $alias d='cd $1'
~ $d ~/Downloads
~/Downloads $d ~/Music
~/Music $d ~/Documents
~/Documents $

To be clear here, my problem has nothing to do with needing to know how to create an alias that accepts argument parameters.

My SPECIFIC problem is when I take the passed argument then try to include it as an argument in another command when that argument has a plus symbol next to the passed arguments variable, which starts with a dollar sign. The answer provided does not work and gives me the same error.

Edit: Based on the first answer given, the solution was to create a FUNCTION within my .bash_profile file, which I did and it worked perfectly!

This is what I added to the profile file:

d() {
  pushd "+$1";
}

And though I don't believe what I am about to say will matter a hill of beans, I will say it anyways:

It is frustrating when people close questions because they assume a certain level of knowledge about the poster. This question was closed with a reference given to a post that teaches people how to write an alias that accepts an argument.

FIRST of all, that was NEVER my question, and SECOND, the proposed answer given in the closing of this question would not have gotten me any closer to a solution.

What I learned from this question and the discussion was that a function within a bash profile script will behave just like an alias. And THAT is the knowledge I needed to solve my problem.

Questions are closed far too easily on this site and in my opinion, arrogantly and without any regard for the actual or probable needs of the OP ... they get closed without any inquiry to the OP in order to determine whether or not the question should remain open ... this is a HUGE failing for this site ... making it too easy for people to dismiss the entire reason why people like us come here in the first place.

Michael Sims
  • 2,360
  • 1
  • 16
  • 29
  • 1
    To quote from (an older version of) [the alias factoid](http://wooledge.org/~greybot/meta/alias) from the bash IRC channel: "If you have to ask, use a function instead". – Charles Duffy Mar 21 '22 at 20:32
  • 1
    `$1` generally doesn't have _any effect whatsoever_ in aliases. It _never_ refers to the arguments of the alias itself -- only to the arguments of the context in which the alias is expanded, and in an interactive shell, that argument list is typically empty. – Charles Duffy Mar 21 '22 at 20:33
  • @CharlesDuffy - well, I have several aliases defined that accept arguments that I then pass into another command and they work perfectly. – Michael Sims Mar 21 '22 at 20:54
  • @CharlesDuffy - Also, I did try to do this with a bash script and I get the same results ... when there is a plus symbol next to the argument variable, it just doesn't work. So I don't see how using a function would work unless I'm missing something? – Michael Sims Mar 21 '22 at 20:56
  • 1
    @MichaelSims I'm pretty sure you're confused about how those aliases that "take arguments" actually work; See the comments under [Nathaniel's answer here](https://stackoverflow.com/questions/7131670/make-a-bash-alias-that-takes-a-parameter/60786547#60786547). Also, try redefining your aliases with the `$1`, `$2`, etc removed, and see if they continue to work (hint: they will, because `$1` etc don't do anything useful in an alias). – Gordon Davisson Mar 21 '22 at 21:23
  • @GordonDavisson - I've no doubt that what you're saying is correct, I simply don't understand what you're saying - I think ... if you look at my edit in my OP, see what I did there with an alias and notice it works ... so what ARE you saying, exactly? – Michael Sims Mar 21 '22 at 21:36
  • Whoever closed this question, made a mistake. My question has NOTHING to do with how to make a bash alias that takes argument parameters. My specific issue has to do with passing an argument into a command from an alias when there is a plus symbol next to the argument variable which starts with a dollar sign. The proposed answer DOES NOT WORK – Michael Sims Mar 21 '22 at 21:44
  • 1
    @MichaelSims Aliases just get literally replaced in the command line, so when you use `d ~/Downloads`, that expands to `cd $1 ~/Downloads`. `$1` then gets replaced by the first argument to the current shell context (*not* the first argument to the alias); usually, you're using this in an interactive shell that doesn't have any arguments, so `$1` expands to the empty string, so it effectively vanishes from the expanded command and it winds up running `cd ~/Downloads`. But try `set -- firstarg secondarg`, then `d ~/Downloads`. It'll expand to `cd firstarg ~/Downloads` and fail. – Gordon Davisson Mar 21 '22 at 21:48
  • @GordonDavisson - Well ... I'm not as educated in bash as you seem to presume, because I have no frame of reference for the understanding of what set -- firstarg even is or does or why I would ever use it. My wielding of bash is limited and on an as-needed basis. I just want to make an alias for the pushd command where I can type a single letter and a number and have the pushs command execute with that number preceded by a plus symbol ... but I think I just figured it out ... I'll exclude the + symbol in the alias and just include it as part of the argument when I use the alias. ( d +3 ) – Michael Sims Mar 21 '22 at 21:56
  • @MichaelSims, to add the bit of knowledge you're missing to follow Gordon's comment: `set -- firstarg` changes `$1` to be `firstarg`. – Charles Duffy Mar 21 '22 at 22:12
  • @MichaelSims, as for your test script, change the last line to `change_to "$@"` so it passes the script's arguments through to the function. But note that a `pushd` (or `cd`) done in a script won't change the caller's directory (since the script is executed in a separate interpreter from the interactive shell that called it), so it's a very useless test. – Charles Duffy Mar 21 '22 at 22:13
  • (also, `pushd` is part of the POSIX sh interactive-extensions annex; it's not guaranteed to be a feature that noninteractive interpreters offer at all, so using it in scripts in the first place is bad form -- note that bash _can_ be compiled without interactive extensions, though the only Linux distro I know to actually distribute a copy built that way is NixOS). – Charles Duffy Mar 21 '22 at 22:16
  • ...also, I hold that the duplicate _is in fact_ correct. You're trying to use `$1` to refer to a parameter. It doesn't work for the reasons the linked duplicate describes, and the techniques it describes fix the problem (when you don't do something silly, like embed your function in a script and not pass arguments through, that compounds the issue by adding new and different problems). – Charles Duffy Mar 21 '22 at 22:19
  • @CharlesDuffy - When you say that ```set --- firstarg``` changes ```$1``` to ```firstarg``` does it do this by utilizing some kind of static assignment in the shell environment somewhere? – Michael Sims Mar 22 '22 at 02:07
  • Not sure what you mean. It changes only the current stack frame -- if you're in a function, only that function has its arguments changed -- so not static in the C sense of the word. – Charles Duffy Mar 22 '22 at 10:51

1 Answers1

0

Use a function instead:

d() { pushd "+$1"; }
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • This doesn't work, did you test it specifically with the pushd command? I did by creating a function exactly as you proposed inside a bash script and I get the same exact error. – Michael Sims Mar 21 '22 at 21:45
  • 1
    @MichaelSims Aliases take precedence over functions, so if you still have the old alias defined it'll be using that instead of the function. Try `type d` to see what's actually being used, and probably `unalias d` to remove the alias so that the function can work. – Gordon Davisson Mar 21 '22 at 21:51
  • See my last edit for the exact way that I tested your solution. – Michael Sims Mar 21 '22 at 22:03
  • @MichaelSims, in your test you aren't passing the script's argument list through to the function. Why are you embedding your function in a script at all? It can just go straight in your `.bashrc` the same way an alias would. – Charles Duffy Mar 21 '22 at 22:10
  • @CharlesDuffy - You are telling me that I can write functions within my .bash_profile file and they will just execute like an alias? – Michael Sims Mar 21 '22 at 22:23
  • @CharlesDuffy - Sir, You're absolutely correct, when I created the function inside the .bash_profile file, it worked perfectly WITH the plus symbol inside the quotes. THANK YOU! – Michael Sims Mar 21 '22 at 22:25
  • 1
    Note that for both aliases and unexported functions, `.bashrc` is generally a better choice than `.bash_profile` (unless your OS vendor changes their tools around to have terminal tabs create login shells and not just interactive shells -- Apple does this, but it's a respect in which their behavior is unusual). Doing things the traditional UNIX way, you have just one "login shell" that sets up your environment variables &c when you first log in -- this sources your `.bash_profile` or `.profile` -- and then later when you start new interactive shells they source `.bashrc` – Charles Duffy Mar 21 '22 at 22:57
  • @CharlesDuffy - Yes, I recently learned about bashrc vs _profile... I use MacOS 99% of the time but deviate to a virtual machine when I need to for whatever reason. I tried making a .bash_profile file in Ubuntu several months ago but was surprised when it wasn't working ... learning by tripping over your own shoe laces ... seems to be the norm in IT ☺ – Michael Sims Mar 22 '22 at 02:04