Shell Alias Which Whitespace Cancelling - macos

When creating an alias for a binary tool in a folder that contains a space, the alias is correctly stored, but when the command is called, the space is evaluated as if it isn't properly cancelled.
The binary is viewable in $PATH. I ran this from zsh 4.3.11 and bash 3.2.48, both with the same result.
Binary Path
~/Test Folder/fooBinary
Alias
alias foo="`which fooBinary`"
This results in
foo='~/Test Folder/fooBinary'
Now calling this alias results in
[shell]: no such file or directory: ~/Test
This used to work to escape the spacing from the alias and I didn't bother to check the version of my older shell or I would go find it.
The I did to actually escape the spacing:
alias foo="'`which fooBinary`'"
My questions:
Why are the spaces evaluated in the quoted alias?
Is there a better way of escaping which?

Aliases have always split on spaces. This is intentional and useful as it allows you to alias arguments, e.g. alias rm='rm -i' or alias commit='git commit -a'.
If you need to quote an argument programmatically, you can use printf %q to add a level of escaping:
alias foo="$(printf %q "$(which fooBinary)")"

Related

Use semicolon character ";" in bash alias

Got a new annoying keyboard and I'm always typing ;s instead of ls.
Is there a way to create a sort of alias for this?
I tried this: alias ;s="ls" but of course it does not work!
You cannot. You can escape the ; when you run the command, but then alias itself informs you that the name is invalid.
$ alias \;s=ls
bash: alias: `;s': invalid alias name
You could define a Readline macro to replace ;s with ls before the shell tries to parse it:
$ bind '";s": "ls"'
This command can be added to your .bashrc file. (You could add it a definition to .inputrc, but it is unlikely you would want to use this macro in any other Readline-aware program.)

Nesting ${name:offset:length} and $() in zsh

In zsh, $() lets me run the command inside the parenthesis and get the stdout, and ${name:offset:length} lets me get a substring of the variable name. How can I nest the former inside the latter? As a concrete example, the following is valid.
base=$(basename $HOME) # basename of user home directory -- temporary
user3=${base:0:3} # first three letters of $base
But can the same thing be achieved without defining the temporary?
I know that user3=$(basename $HOME | cut -c 1-3) will do the trick, but I'm looking for a solution that doesn't use cut.
Double quotes around the command substitution should work:
user3=${"$(basename $HOME)":0:3}
Though, I'd be inclined to use zsh's :t modifier instead of basename:
${${HOME:t}:0:3}
The :offset:length form is only really there for bash compatibility. If you might have an old version of zsh you can also use the subscript form:
${${HOME:t}[0,3]}

Create shell alias with semi-colon character

I've noticed that I have a tendency to mistype ls as ;s, so I decided that I should just create an alias so that instead of throwing an error, it just runs the command I mean.
However, knowing that the semi-colon character has a meaning in shell scripts/commands, is there any way to allow me to create an alias with that the semi-colon key? I've tried the following to no avail:
alias ;s=ls
alias ";s"=ls
alias \;=ls
Is it possible to use the semi-colon as a character in a shell alias? And how do I do so in ZSH?
First and foremost: Consider solving your problem differently - fighting the shell grammar this way is asking for trouble.
As far as I can tell, while you can define such a command - albeit not with an alias - the only way to call it is quoted, e.g. as \;s - which defeats the purpose; read on for technical details.
An alias won't work: while zsh allows you to define it (which, arguably, it shouldn't), the very mechanism that would be required to call it - quoting - is also the very mechanism that bypasses aliases and thus prevents invocation.
You can, however, define a function (zsh only) or a script in your $PATH (works in zsh as well as in bash, ksh, and dash), as long as you invoke it quoted (e.g., as \;s or ';s' or ";s"), which defeats the purpose.
For the record, here are the command definitions, but, again, they can only be invoked quoted.
Function (works in zsh only; place in an initialization file such as ~/.zshrc):
';s'() { ls "$#" }
Executable script ;s (works in dash, bash, ksh and zsh; place in a directory in your $PATH):
#!/bin/sh
ls "$#"

alias wont work - embedding a quoted string in an alias definition

Im trying to make an alias on my mac terminal in zsh shell.
some info when i do echo $SHELL i get /bin/zsh proving im using the zsh shell.
mac has a command you can use to open things in chrome like this :
open -a "google chrome" myfile.html
I need to make an alias of this but it wont work but other aliases work.
i would like the alias to run like this
chrome myfile.html
here is my alias file:
alias x="echo \'y "
alias chrome="open -a \'google chrome\' "
so if i run x at the prompt y does get outputed but if i run chrome at the command line it says it cant find the file. Do i have to use xargs or something ?
Note: This answer applies not only to zsh, but to bash and ksh as well.
Try:
alias chrome='open -a "Google Chrome"'
By using single quotes around the entire definition (which is generally preferable when defining an alias, so as to prevent premature expansion of the string at alias definition time rather than at execution time), you can use double quotes inside without escaping.
The problem with your definition was that \' literally became part of the alias (rather than just ') - there is no need to escape ' in a double-quoted string literal.
Thus, you can also use the following (but, as stated, using single quotes to enclose the entire definition is preferable):
alias chrome="open -a 'Google Chrome'"
You don't need to quote the single quotes within the double quotes, otherwise you'll end up with literal quotes. Just try it with echo:
$ alias chrome="echo open -a \'google chrome\' "
$ chrome
open -a 'google chrome'
The quotes that are shown here are literal parts of the argument.
Just use one of:
alias chrome="open -a 'google chrome'"
alias chrome='open -a "google chrome"'
alias chrome="open -a \"google chrome\""
All of them are equivalent.

Can I have a shell alias evaluate a history substitution command?

I'm trying to write an alias for cd !!:1, which takes the 2nd word of the previous command, and changes to the directory of that name. For instance, if I type
rails new_project
cd !!:1
the second line will cd into the "new_project" directory.
Since !!:1 is awkward to type (even though it's short, it requires three SHIFTed keys, on opposite sides of of the keyboard, and then an unSHIFTed version of the key that was typed twice SHIFTed), I want to just type something like
cd-
but since the !!:1 is evaluated on the command line, I (OBVIOUSLY) can't just do
alias cd-=!!:1
or I'd be saving an alias that contained "new_project" hard-coded into it. So I tried
alias cd-='!!:1'
The problem with this is that the !!:1 is NEVER evaluated, and I get a message that no directory named !!:1 exists. How can I make an alias where the history substitution is evaluated AT THE TIME I ISSUE THE ALIAS COMMAND, not when I define the alias, and not never?
(I've tried this in both bash and zsh, and get the same results in both.)
For bash:
alias cd-='cd $(history -p !!:1)'
Another way to accomplish the same thing:
For the last argument:
cd Alt-.
or
cd Esc .
For the first argument:
cd Alt-Ctrl-y
or
cd Esc Ctrl-y
For zsh:
alias cd-='cd ${${(z)$(fc -l -1)}[3]}'
How this works:
$(fc -l -1) is evaluated. fc -l {start} [{end}] means «list history commands from {start} till {end} or last if {end} is not present».
${(z)...} must split ... into an array just like the shell does (see «Parameter Expansion Flags» in man zshexpn), but in fact it splits on blanks. Maybe it is only my bug.
${...[3]} takes third value from the array. First value is a number of a command, second is command and third and later are arguments.

Resources