Custom terminal command using bash_profile - terminal

I am trying to make a new command which runs a shell script that takes in arguments.
So, I have the command in my .bash_profile:
command() {
/Users/myname/filepath/MyScript.sh
}
but MyScript.sh can take in arguments. So how can I modify this code to handle arguments so that it will pass those arguments to MyScript.h?

I think you're looking for a bash alias:
alias mycommand="/Users/myname/filepath/MyScript.sh $#"

Assuming you want all parameters to command to go to MyScript.sh, then try this:
command() {
/Users/myname/filepath/MyScript.sh "$#"
}

Related

Export a function from zsh to bash script

I have a function defined in my .zshenv like this:
function my_func() {
echo $1
}
I then execute a bash script from the zsh which its content is:
type my_func
I got an error: /tmp/test.bash: line 3: type: my_func: not found
While if I type type my_func from the zsh I got: my_func is a shell function from
Is there a way to use zsh defined function in a bash script? It seems to work for the exported variables
How bash does it
Bash itself can export its functions to other bash shells. It does so by exporting a string environmental variable of the form:
BASH_FUNC_functionNameHere%%=() { functionBodyHere; }
So in theory you could use the following zsh-command to export your function for bash:
export "BASH_FUNC_my_func%%=() { $(echo; typeset -f my_func | tail -n+2) }"
However, this does not work because zsh doesn't allow %% in identifiers.
Workaround
Depending on how you start bash, you might be able to inject the function definition into the bash process.
When running a bash script like bash myScript or ./myScript you can use bash -c "$(typeset -f my_func); export -f my_func; myScript" instead.
When starting an interactive bash shell using bash, you can use bash -c "$(typeset -f my_func); export -f my_func; exec bash" instead.
The right way
Either way, your function has to be a polyglot. That is, the source code of the function has to be understood by both zsh and bash. Above approach is not really viable if you want to export many functions or want to call many bash scripts.
It would be easier to define each of your functions inside its own script file and add the locations of those scripts to $PATH. That way you can call your "functions" from every shell and they will always work independently from your current shell.
Replacing the functions by script files only works if your functions don't want to modify the parent shell. cd or setting variables has no effect on the caller. If you want to do stuff like this, you can still use a script file, but then have to source it using . myFunctionFile. For sourcing, the source code has to be a polyglot again.

Bash function variable command not found error

I have a bash script like this with a function
_launch()
{
${1}
}
testx()
{
_launch "TESTX=1 ls -la"
}
testx
I get error "TESTX=1 command not found" in _launch function. Why?
When I run TESTX=1 ls -la directly on shell it works fine.
It's not a good idea to use variables to hold commands. See BashFAQ/050
As long as you are dealing with executables and not shell built-ins, you could do this:
_launch() {
env $1
}
This won't play well in case you have literal spaces in values used in var=value pairs or arguments to the command being launched.
You can overcome this problem by just passing the command to the launch function and setting your variables in function invocation itself, like this:
_launch() {
# your launch prep steps here...
"$#" # run the command
# post launch code here
}
TESTX=1 TESTY=2 TESTZ=3 _launch ls -la
The variables would be passed down to the launched command as environment variables.
You get the error because first looks at the statement to see whether we have a variable assignment, and then does parameter expansion. In your case, bash doesn't recognize that you want to extend the environment for your ls command, and treats TESTX=1 as command to be executed.
For the same reason, the following does not set the bash variable ABC:
x='ABC=55'
$x
This would print ABC=55: command not found.

Create an alias of the script by calling the script with an argument: ./myscript alias

I would like to be able to create an alias of my script by calling it with an argument.
$ ./devbox alias
$ devbox <other command of my script>
Here is the code of my bash script:
#!/bin/bash
shopt -s expand_aliases
aliasDevbox()
{
alias devbox="./devbox"
}
parseCli()
{
command=$1
case "$command" in
"alias") aliasDevbox
;;
esac
}
parseCli "$#"
It's actually not working: command not found
(I know that if my code alias devbox="./devbox" was at the beginning of my script, I would be able to call it this way source ./devbox and it would work.)
Thank you!
This won't and can't work because ./devbox is a child process of your shell, and child processes can't set aliases in parent shells. (Similarly, they can't change environment variables either.)
I can suggest workarounds, but taking a step back, is this really needed? Typically, users will set up aliases in a login script such as .bashrc so that the aliases are automatically available in any new shell they start. My suggestion is simply to write some documentation suggesting that users create an alias for your tool to make it easier to use.

Failing to modify .bashrc

My .bashrc file contains:
# mkdir, cd into it
function mkcd ()
{
mkdir -p "$*"
cd "$*"
}
When I type mkcd in shell I get mkcd: Command not found.
when I type source ~/.bashrc I get an error:
Badly placed ()'s.
by the way, my text editor (emacs) is recognising the code as Shell-script[tcsh].
How do I fix this?
If you can accept the restriction that you have to pass the name of the directory to be created as the first argument, it should look like this:
# mkdir, cd into it
function mkcd ()
{
mkdir -p "$#"
cd "$1"
}
You need to run source ~/.bashrc to see it working (or alternatively start a new shell).
Three comments on that function. This will work mostly. To catch some corner cases:
Either use function mkcd { ...; } or mkcd() { ...; }. The first is compatible with ksh, but only if you drop the (). The mkcd() notation is the standard POSIX notation.
Even mkdir -p can fail, so make the cd conditional on mkdir.
Finally, you want exactly one argument to mkdir and cd. Use only one argument, and test that it has a value with the :? modifier in parameter substitution. This will stop the function from sending you $HOME.
Together:
function mkcd
{
mkdir -p "${1:?}" && cd "${1}"
}
Put that in your .bashrc and open a new shell. Type type mkcd. This should respond with:
mkcd is a function, followed by its definition.
I ran your mkcd function on bash 4.2.45 and linux 3.8.0 and it worked as expected. Logging on in a fresh window or running
source ~/.bashrc
in your existing window should define the function for you. If it does not work you'll get an error message like:
mkcd: command not found
While hek2mgl's suggestion is not necessary to make it work, it does make it make more sense since you're only going to cd to one directory.
As commented by Henk Langeveld and hek2mgl: "Wrong shell. Badly placed ()'s is a message produced by tcsh. Switch to bash or ksh."
I thought that opening a terminal on ubuntu entered straight into bash environment. In fact, as commented below, "a Terminal will start a copy of your login shell as defined in /etc/passwd". By typing ps -p $$ in terminal, I realise mine is set to tcsh, the C shell. In that case, one needs to type bash to get into bash environment.
Then source ~/.bashrc compiles the definition for mkcd.

Call bash function in IRB

If I run a custom bash function under shell console:
~/w/dotfiles/ruby [g:master-] ΒΆ repository_root
/Users/tian/Documents/workspace/dotfiles
And if I run the custom bash function under IRB:
irb(main):001:0> `repository_root`
(irb):1: command not found: repository_root
=> ""
How could I get the same result in IRB?
# declare
repository_root () {
if git_is_repository ; then
git_show_repository_root
fi
}
Assuming your function is in one of your bash profile files, you want to start up an interactive (-i) login (-l) shell to execute (-c) your function:
output = %x{bash -lic 'repository_root'}
One way to do this is to make a command out of the function.
Here's a short how-to
Create a shell script file that calls the function.
Create a .bin directory in your HOME and add it to $PATH in .bash_rc.
Place the shell script file in .bin.
source .bash_rc to update the $PATH variable you just changed.
Assuming you named the file fnx, just use the back tick operator or exec to run
the command - exec("fnx")
where is repository_root declared?
.bash_profile? .bashrc?
try to source that file before using repository_root
`. /path/to/file/declaring/repository_root; repository_root`

Resources