alias parameter not working - bash

I am trying to make it easier to use scp so I learned about alias today, and I am using it like this:
alias loudie-scp="scp -i keys/aws.pem $1 ec2-user#ec2-107-20-68-112.compute-1.amazonaws.com:/home/ec2-user"
the $1 is there to specify the file i want to transfer over. However this is not working and giving me an error:
scp: /home/ec2-user: not a regular file
This does not happen when I execute this command manually passing in any file for $1.

BASH FAQ entry #80: "How can I make an alias that takes an argument?"

Unfortunately BASH aliases are kind of like find-and-replace -- they're not very powerful for the sort of task you describe. I would suggest using, instead, a script file and placing it in an executable directory; something like so:
#!/bin/bash
scp -i keys/aws.pem $1 ec2-user#ec2-107-20-68-112.compute-1.amazonaws.com:/home/ec2-user
Then, given that it has the name loudie-scp you could call it like so:
loudie-scp <parameter>

As I'm sure Ignacio's link will explain, an alias does nothing more than textually expand the alias to its value. It does not take arguments, you need to use a function for that.

Related

Use content of file as part of a Bash command

I want to use the content of a file.txt as part of a bash command.
Suppose that the bash command with its options that I want to execute is:
my_command -a first value --b_long_version_option="second value" -c third_value
but the first 2 options (-a and --b_long_version_option ) are very verbose so instead of inserting directly on the command line (or bash script) I wrote them in a file.txt like this:
-a first value \
--b_long_version_option="second value"
Now I expect to call the command "my_command" with the following syntax (where "path_to/file.txt" is the path to file.txt, expressed in relative or absolute form):
my_command "$(cat path_to/file.txt)" -c third_value
This however is not the right syntax, as my command is breaking and complaining.
How should I write the new version of the command and/or the file.txt so that it is equivalent to its native bash usage?
Thanks in advance!
The quotes are preserving the newlines. Take them off.
You also don't need the cat unless you're running an old bash parser.
my_command $(<path_to/file.txt) -c third_value
You'll need to take the backslashes at the ends of lines out.
Be careful doing things like this, though. It's probably better to just put the whole command in the file, rather than just pieces of it. If you really just want arguments, maybe define them a little more carefully in an array, source the file and then apply them, like this:
in file:
myArgs=( "-a" "first value"
"--b_long_version_option=second value"
)
Note the quoting. Then run with
. file
my_command "${myArgs[#]" -c third_value
e.g.,
$: printf "[%s] " "${myArgs[#]}" -c=foo
[-a] [first value] [--b_long_version_option=second value] [-c=foo]
I haven't seen any example of what you're trying. But, there are simpler ways to achieve your goal.
Bash Alias
ll for example is a bash alias for ls -al. It usually is defined in .bash_profile or .bashrc as follows :
alias ll='ls -al'
So, what you can do is to set another alias for your shorthand command.
alias mycmd='mycommand -a first value --b_long_version_option="second value"'
then you can use it as follows :
mycmd -c third_value
Config file
You can also define a mycommand.json file or mycommand.ini file for default arguments. Then, you will need to check for config file in your software, and assign arguments from it.
Using config file is more advanced solution. You can define multiple config files. You can set default config file in /etc/mycommand/config.ini for example. When running on different directories, you should check ${cwd}/mycommand.ini to check local config file exists or not. You can even add a --config-file argument to your command.
Using alias is more convenient for small tasks, or thing that won't change much. If your command's behavior should be different in some other project, the using a config file would be a better solution.

How to set part of a path dynamically for alias command in bashrc file

I'm trying to have a alias command and the part of its path keeps changing.
Eg:
/var/mywork/swag/wsnew/
/var/mywork/swag/ws/
/var/mywork/swag/wsold/
and my alias command to achieve is something link this
alias cws='cd /var/mywork/swag//
since last directory in the path is keep changing. I wanted to get automatically update in alias command. Is there anyway ?
I tried something like
alias cws='cd /var/mywork/swag/getenv("WSP")/
so whenever I set WSP to required path it automatically takes. But it didn't help.
Like most problems with aliases, this is easier to solve with a shell function:
cws() {
cd /var/mywork/swag/"$WSP"
}
Like melpomene said, you are better off using a function, but if you, for whatever reason, want to stick with an alias, you can do
alias cws='cd /var/mywork/swag/$WSP'
But note that this differs from using a shell function in one point, which is related to setting a variable for just one command: If you write
WSP=aaa
...
WSP=xxx
...
WSP=yyy cws
and cws is defined as a function, this would cd to yyy, but if it is an alias, it would cd to xxx.

Shell script: shorten or aliasing an address after a command

I want to abbreviate or set an alias to a destination address every time I use while copying files. For example,
scp <myfile> my_destination
where my_destination could be hbaromega#192.168.1.100:Documents. So I want to modify my .bash_profile by inserting something like
alias my_destination = 'hbaromega#192.168.1.100:Documents' .
But that doesn't work since my_destination is not a command.
Is there a way out?
Note: I don't want to abbreviate the whole command, but only the address, so that I can use it with other possible commands.
You can't do what you want for the reason you state (an alias defines an entire command). But you could use a shell function to come close:
my_scp() {
scp "$#" hbaromega#192.168.1.100:Documents/.
}
which you could then call as
my_scp *.c
(Using $# in doublequotes is shell black magic that avoids trouble if any of the file names matched by the *.c glob contain spaces)
Of course, if you don't want to define a function, you could always use a shell variable to at least save the retyping:
dest='hbaromega#192.168.1.100:Documents/.'
scp *.c $dest
You have a couple options. You can set hostname aliases in your ~/.ssh/config like this:
Host my_destination
Hostname 192.168.1.100
User hbaromega
You could use it like this:
$ scp myfile my_destination:Documents/
Note that you'd still have to specify the default directory.
Another option would be to just put an environment variable in your ~/.bashrc:
export my_destination='hbaromega#192.168.1.100:Documents/'
Then you could use it like this:
$ scp myfile $my_destination
BertD's approach of defining a function would also work.
I think this works without using export as well since anyway I am assigning a variable for the path or destination. So I can just put the following in my .basrc or .bash_profile :
my_destination='hbaromega#192.168.1.100:Documents/'
Then
scp <myfile> $my_destination
Similarly I can execute any action (e.g. moving a file)for any local destination or directory:
local_dest='/Users/hbaromega/Documents/'
and then
mv <myfile> $local_dest
In summary, a destination address can be put as a variable, but not as a shell command or function.
The reason it does not work is there are spaces surrounding the = sign. As pointed out, an alias must be called as the first part of the command string. You are more likely to get the results you need by exporting my_destination and then calling it with a $. In ~/.bashrc:
export my_destination='hbaromega#192.168.1.100:Documents'
Then:
scp <myfile> $my_destination
Note: you will likely need to provide a full path to Documents in the export.

Preprocess line before it is processed by bash

Is there a way to preprocess a line entered into bash in interactive mode before it is processed by bash?
I'd like to introduce some custom shorthand syntax to deal with long paths. For example, instead of writing 'cd /one/two/three/four/five', I'd like to be able to write something like 'cd /.../five', and then my preprocessing script would replace this by the former command (if a unique directory 'five' exists somewhere below /).
I found http://glyf.livejournal.com/63106.html which describes how to execute a hook function before a command is executed. However, the approach does not allow to alter the command to be executed.
There's no good way of doing this generally for all commands.
However, you can do it for specific commands by overriding them with a function. For your cd case, you can stick something like this in your .bashrc:
cd() {
path="$1"
[[ $path == "/.../five" ]] && path="/one/two/three/four/five"
builtin cd "$path"
}
In bash 4 or later, you can use the globstar option.
shopt -s globstar
cd /**/five
assuming that five is a unique directory.
The short answer is not directly. As you have found, the PROMPT_COMMAND environment variable allows you to issue a command before the prompt is displayed, which can allow for some very creative uses, e.g. Unlimited BASH History, but nothing that would allow you to parse and replace input directly.
What you are wanting to do can be accomplished using functions and alias within your .bashrc. One approach would be to use either findutils-locate or simply a find command to search directories below the present working directory for the last component in the ellipsed path, and then provide the full path in return. However, even with the indexing, locate would take a bit of time, and depending on the depth, find itself may be to slow for generically doing this for all possible directories. If however, you had a list of specific directories you would like to implement something like this for, then the solution would be workable and relatively easy.
To provide any type of prototype or further detail, we would need to know more about how you intent to use the path information, and whether multiple paths could be provided in a single command.
Another issue arises if the directory five is non-unique...

Using "nice" command with an alias

How can I use the "nice" command with an alias?
As an example:
alias list=ls
list # works
nice -10 list # doesn't work
How could I make that last line work?
Alias is a shell feature, and nice is an external program:
$ type nice
nice is hashed (/usr/bin/nice)
It's the program nice that runs the command passed as an argument, calling the C function execve, so all the arguments for it need to be evaluated BEFORE the call.
So, it would probably better not to use an alias and simply put the whole command needed there, but if you really want to, you could try something like this:
$ nice -10 `alias list | sed "s/^\(alias \)\?[^=]\+='//; s/'$//;"`
alias list prints the alias definition in the format alias list='ls' (or list='ls', if it's /bin/sh), so I did some sed substitutions there to get only the command it expands to.
If you're sure to use only bash you can use ${BASH_ALIASES[list]} instead, as pointed out in the comments:
$ nice -10 ${BASH_ALIASES[list]}
Though perhaps not as exotically exciting as nice -10 $UserVar1; or nice -10 ${BASH_ALIASES[list]}, you may also have the nice -10 list you asked for, though via wrapper script instead of alias:
# one-time setup
mkdir -p ~/.local/aliases
echo 'PATH=$HOME/.local/aliases:$PATH' >> ~/.bashrc
# open new terminal window, or
source ~/.bashrc
# create the wrapper. $# to passthrough args.
echo 'ls $#' > ~/.local/aliases/list
chmod +x ~/.local/aliases/list
nice -10 list # works :)
nice -10 list --color=always -lathr # args passthrough also works :)
For Zsh BASH_ALIASES will not work. So you may use it like this:
nice -10 `list`
This is a bad idea. You are defining a command alias but are not even using it as an alias expansion. Poor coding practice here. This is what you want.
declare -x UserVar1='ls';
nice -10 $UserVar1;
And if you will not change the definition of UserVar1 later on in your code. There are zero reasons you can justify to use a variable instead of the actual command name.
You are headed for disaster. Plain and simple. Use a variable or the command name itself it is far safer and marginally more efficient and easier to read.

Resources