I want to create an alias alias gohost "ssh \!:1-machine" so that I can do gohost one and it will do ssh one-machine or gohost two and it will do ssh two-machine.
But this alias says:
Bad ! arg selector.
Probably because there is no space around the selector in the alias. How to do this?
In case some lost soul comes here searching for answers, here it is:
"ssh \!:1\-machine"
i.e. escape the "-"
Related
Currently trying to move all of my aliases from .bash_profile to .zshrc. However, found a problem with one of the longer aliases I use for substituting root to ubuntu when passing a command to access AWS instances.
AWS (){
cd /Users/user/aws_keys
cmd=$(echo $# | sed "s/root/ubuntu/g")
$cmd[#]
}
The error I get is AWS:5: command not found ssh -i keypair.pem ubuntu#ec1.compute.amazonaws.com
I would really appreciate any suggestions!
The basic problem is that the cmd=$(echo ... line is mashing all the arguments together into a space-delimited string, and you're depending on word-splitting to split it up into a command and its arguments. But word-splitting is usually more of a problem than anything else, so zsh doesn't do it by default. This means that rather than trying to run the command named ssh with arguments -i, keypair.pem, etc, it's treating the entire string as the command name.
The simple solution is to avoid mashing the arguments together, so you don't need word-splitting to separate them out again. You can use a modifier to the parameter expansion to replace "root" with "ubuntu". BTW, I also strongly recommend checking for error when using cd, and not proceeding if it gets an error.
So something like this:
AWS (){
cd /Users/user/aws_keys || return $?
"${#//root/ubuntu}"
}
This syntax will work in bash as well as zsh (the double-quotes prevent unexpected word-splitting in bash, and aren't really needed in zsh).
BTW, I'm also a bit nervous about just blindly replacing "root" with "ubuntu" in the arguments; what if it occurs somewhere other than the username, like as part of a filename or hostname?
I'm trying to do an rsync like this in a bash script;
rsync -e "ssh ${flags_ssh}" -avRz --rsync-path="sudo rsync" $direcNew $(eval echo ${user_name})#$(eval echo ${instance_address}):$(eval echo ${mountdir}`)
However, when I run this using bash -x like this:
bash -x ./myscript
I get that it's trying to run that command except with the option rsync-path looking like
'--rsync-path=sudo rsync'
How do I prevent this? I need the double quotes to stay and the single quotes to go away, I don't know why it's happening, and I've tried endless combinations of eval and backslashes with no success.
You don't need to prevent this. What's happening is that when the shell parses --rsync-path="sudo rsync", it removes the quotes (after they have the intended effect of having the space treated as part of the argument, rather than a separator between arguments). Then, when it sees it's in -x mode, it comes up with a representation that would have led to the space being treated that way, and prints that. It could print any equivalent representation, including (but not limited to) any of these:
--rsync-path="sudo rsync"
"--rsync-path=sudo rsync"
--rsync-path=sudo\ rsync
--rsync-path=sudo" "rsync
'--rsync-path=sudo rsync'
$'--rsync-path=sudo rsync'
...etc
The fact that it picked a different representation than you did is not important, because these are all fully equivalent -- they all result in exactly the same thing being passed as an argument to rsync, so you don't need to worry about it.
You also intrinsically can't "fix" it, because by the time the shell prints its interpretation of your command, it's already forgotten which representation you happened to use -- it only knows the resulting argument that's going to be passed to rsync. In order to get it to print something else, you'd have to be passing a different actual argument to rsync, and that would break your rsync command.
As a terminal noob, I've created aliases for pretty much everything I do. The problem is that I've started forgetting those few commands that I do know because of it. On top of that, I sometimes need to edit a variable in the previous command.
So what I'd like is if when I use an alias, the first line printed is the actual command it represents, then proceed to execute the command. Since pressing up and !! simply reprints the alias, I'm not too sure how to get a reference to the underlying command.
Thanks.
You can always use:
alias to list all your aliases, or
alias name to show the specification of the alias name.
So in fact you can define your alias as
alias myalias="alias myalias; <do stuff>"
I also think that chepner's answer with Alt-Control-e is more practical, but I am posting this for completeness.
After you type your alias, but before you hit enter, you can type Meta-Control-e (probably Alt-Control-e, but possibly Esc-Control-e) to expand what you've typed; this will expand any aliases and history expansions so you can see the "long" form of what you've typed.
You can use variables in your alias to get a clean output:
alias test='_TMP="pushd /home/a/b/c";echo $_TMP; eval $_TMP'
If you want to avoid messages coming out of alias, you can do
_TMP="pushd /home/a/b/c >/dev/null 2>&1"
It does add an environment var of _TMP.
The old post had error in it.
I want to write a script that will change to different directories depending on my input. something like this:
test.sh:
#!/bin/bash
ssh machine001 '(chdir ~/dev$1; pwd)'
But as I run ./test.sh 2 it still goes to ~/dev. It seems that my argument gets ignored. Am I doing anything very stupid here?
Bash ignores any variable syntax inside the single-quoted(') strings. You need double quotes(") in order to make a substitution:
#!/bin/bash
ssh machine001 "(chdir ~/dev$1; pwd)"
The parameter is enclosed in single quotes, so it isn't expanded on the local side. Use double-quotes instead.
#!/bin/bash
ssh machine001 "chdir ~/dev$1; pwd"
There's no need for the (...), since you are only running the pair of commands then exiting.
Say I have the following alias.
alias pwd_alias='echo `pwd`'
This alias is not "dynamic". It evaluates pwd as soon as the shell starts. Is there anyway to delay the evaluation of the expression in the ticks until the alias's runtime?
What you really want is a function, instead of an alias.
pwd_alias() {
echo "$PWD"
}
Aliases do nothing more than replace text. Anything with complexity calls for a function.
As jordanm said, aliases do nothing more than replace text.
If you want the argument of echo to be the output of pwd expanded by bash, then I don't understand your question.
If you want the argument of echo to be `pwd` with the backquotes kept, it's indeed possible, for example:
alias a="echo '\`pwd\`'"
So, if instead of echo you have something which does backquote expansion in its own runtime, maybe that's what you want.
I do not believe you can change the evaluation from occurring at shell start. Since the processes of creating the alias is run at shell start the pwd is evaluated then. You could simple change the alias to just run pwd without the back ticks as pwd outputs without the need to echo. A simple way to resolve this is to change from using an alias to a shell script in your path if you do not wish to change from using an alias.
#!/bin/bash
pwd