Alias with variable in bash [duplicate] - linux

This question already has answers here:
Make a Bash alias that takes a parameter?
(24 answers)
Closed 5 years ago.
I want to create an alias in bash like this:
alias tail_ls="ls -l $1 | tail"
Thus, if somebody types:
tail_ls /etc/
it will only show the last 10 files in the directory.
But $1 does not seem to work for me. Is there any way I can introduce variables in bash.

I'd create a function for that, rather than alias, and then exported it, like this:
function tail_ls { ls -l "$1" | tail; }
export -f tail_ls
Note -f switch to export: it tells it that you are exporting a function. Put this in your .bashrc and you are good to go.

alias tail_ls='_tail_ls() { ls -l "$1" | tail ;}; _tail_ls'

The solution of #maxim-sloyko did not work, but if the following:
In ~/.bashrc add:
sendpic () { scp "$#" mina#foo.bar.ca:/www/misc/Pictures/; }
Save the file and reload
$ source ~/.bashrc
And execute:
$ sendpic filename.jpg
original source: http://www.linuxhowtos.org/Tips%20and%20Tricks/command_aliases.htm

You can define $1 with set, then use your alias as intended:
$ alias tail_ls='ls -l "$1" | tail'
$ set mydir
$ tail_ls

tail_ls() { ls -l "$1" | tail; }

If you are using the Fish shell (from http://fishshell.com ) instead of bash, they write functions a little differently.
You'll want to add something like this to your ~/.config/fish/config.fish which is the equivalent of your ~/.bashrc
function tail_ls
ls -l $1 | tail
end

Related

How to alias an option?

I am making a bash script where I want to alias some commands. I want to alias rm to, let's say ls:
alias rm="ls"
But then I also want to add custom options to my aliased rm command. I want to add -u. I can't do (for example):
alias rm -u="ls dir1"
The code above throws an error. My question is, how do I alias options to commands? So how do I make custom options? Thanks in advance.
As stated in the comments; altering the function of rm could result in unexpected behaviour; use with caution
The Bash documentation states: 1
For almost every purpose, shell functions are preferred over aliases.
A bash function that will override rm -u could look like this:
rm() {
if [[ "$#" == "-u" ]]; then
ls dir1
else
ls
fi
}
Where
rm -u will run ls dir1
Every other rm * will run ls
You do not want to do this method, but: anyway, you can do:
$ alias somerm="ls "
$ alias -- -u=dir1
$ somerm -u
ls: cannot access 'dir1': No such file or directory
The trailing space in an alias causes alias to be applied on the next word on the command line, in this case on -u, which alias substitutes for dir1.
How do I make custom options?
Options:
write your own utility from scratch with the added option
patch the utility with your own option and distribute it (preferably with a different name and configure your shell to use your own utility instead of standard one)
create a wrapper around the utility to "catch" the new options and apply custom semantics to the utility (ie. a function, as in the other answer).
rm as a function, using (IMO) proper option parsing:
rm () {
local OPTIND OPTARG
local real_command="ls"
local command_args=()
while getopts :u opt; do
case $opt in
u) command_args+=( "dir1" ) ;;
?) echo "unknown option: -$OPTARG" >&2
return 1
;;
esac
done
shift $((OPTIND - 1))
"$real_command" "${command_args[#]}" "$#"
}
Just a smidge more verbose than an alias, but that's the way bash is.

Why are the results from terminal and bash script different? [duplicate]

This question already has answers here:
How to use aliases defined in .bashrc in other scripts?
(6 answers)
Closed 1 year ago.
USER#HOST:~:$ cat .bashrc
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific aliases and functions
alias sudo='sudo -i'
USER#HOST:~:$ cat tmp.sh
#!/bin/bash
sudo env | grep PATH
USER#HOST:~:$ ./tmp.sh
PATH=/usr/bin:/bin:/usr/sbin:/sbin
USER#HOST:~:$ sudo env | grep PATH
PATH=/usr/python-3.8.2-r2/bin:/usr/jdk64/jdk1.8.0_112/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/bin:/root/bin
I put an alias setting in my .bashrc file.
When I test it through a terminal, it's okay.
But it seems to work differently when done with a script.
What's the difference here, and how can I test this through script?
The alias does not apply to the script. You'll see the equivalent if you use command to bypass alias expansion in the shell:
$ command sudo env | grep PATH

Execute bash on logon and add alias

When I login to a Linux server per Putty, I want to execute the bash (because the default shell is another) and after that adding an alias.
I tried several combinations of putting exec bash in the .profile and adding alias foo='echo foo' into .bash_profile. But I didn't find out the correct combination. Either the alias wasn't set, or the bash wasn't executed.
So, the question is, in which of these files:
.profile
.bashrc
.bash_profile
do I have to put these commands:
exec bash
alias foo='echo foo'
to run the bash shell and have access to my alias every time I login to the server?
edit: We're using all the same user to login. But I want to execute the bash and adding the alias only for my remote machine. I do already have a suitable if statement for that. I only have to know, where to put these commands!
edit2:
What I have so far in my .profile:
if [ $(who -m | awk '{print $NF}' | grep "myHostName" | wc -l) -eq 1 ]
then
exec bash
alias foo='echo foo'
fi
This will execute the bash for only my user. But the alias will be ignored, since I'm starting a new shell and the alias will be probably set in the old shell...
Going to go out on a limb and guess you want to do this because your default shell isn't bash. Don't. Just change your default shell
> chsh -s /bin/bash
Then put
alias foo='echo foo'
In either ~/.bashrc or ~/.bash_profile
If multiple users are using the same account, you can try to do the following. While logged in, run
> who -a | grep $(ps -p $PPID -o ppid=) | awk '{print $NF}'
This may be system dependent, but on a couple I tried it on, this will get location you're logged in from. Once you have that output, do the following
if [[ $(who -a | grep $(ps -p $PPID -o ppid=) | awk '{print $NF}') == output ]]; then
alias foo='echo foo'
done
If you're ssh-ing from multiple computers, then I don't think there is any way to do what you want. Simplest would be to make your own file in the home directory, and then source it manually each time you log in.
e.g.
> touch myfile.txt
> echo "alias foo='echo foo'" >> myfile.txt
> source myfile.txt
> foo
foo
So you would just have to run source myfile.txt each time you log in or just have putty source it by default.
Okay, finally I figured it out by myself with the great help of BroSlow.
I wrote the following to my .profile:
if [ $(who -m | awk '{print $NF}' | grep "myHostName" | wc -l) -eq 1 ]
then
exec bash
fi
and the other part to the .bash_profile:
if [ $(who -m | awk '{print $NF}' | grep "myHostName" | wc -l) -eq 1 ]
then
alias foo='echo foo'
fi
This solved my problem!
On logon, the .profile will be sourced automatically and will execute the bash.
After that the .bash_profile will be sourced due to the fact, that the bash shell will source it's own profile.
However: thanks a lot for the support!
To set up alias in startup change your .bash_profile
Add alias to bash profile:
$ cd
$ sudo nano .bash_profile
$ alias ALIAS_NAME='COMMAND'
Update bash profile
$ source ~/.bash_profile

How can I list the path of the output of this script?

How can I list the path of the output of this script?
This is my command:
(ls -d */ ); echo -n $i; ls -R $i | grep "wp-config.php" ;
This is my current output:
/wp-config.php
It seems you want find the path to a file called "wp-config.php".
Does the following help?
find $PWD -name 'wp-config.php'
Your script is kind of confusing: Why does ls -d */ does not show any output? What's the value of $i? Your problem in fact seems to be that ls -R lists the contents of all subdirectories but doesn't give you full paths for their contents.
Well, find is the best tool for that, but you can simulate it in this case via a script like this:
#!/bin/bash
searchFor=wp-config.php
startDir=${1:-.}
lsSubDir() {
local actDir="$1"
for entry in $(ls "$actDir"); do
if [ -d "$actDir/$entry" ]; then
lsSubDir "$actDir/$entry"
else
[ $entry = $searchFor ] && echo "$actDir/$entry"
fi
done
}
lsSubDir $startDir
Save it in a file like findSimulator, make it executable and call it with the directory where to start searching as parameter.
Be warned: this script is not very efficient, it may stop on large subdirectory-trees because of recursion. I would strongly recommend the solution using find.

Linux script: Reinterpret environment variable

I am creating a Bash script which reads some other environment variables:
echo "Exporting configuration variables..."
while IFS="=" read -r k v; do
key=$k
value=$v
if [[ ${#key} > 0 && ${#value} > 0 ]]; then
export $key=$value
fi
done < $HOME/myfile
and have the variable:
$a=$b/c/d/e
and want to call $a as in:
cp myOtherFile $a
The result for the destination folder for the copy is "$b/c/d/e", and an error is shown:
"$b/c/d/e" : No such file or directory
because it is interpreted literally as a folder path.
Can this path be reinterpreted before being used in the cp command?
You need eval to do this :
$ var=foo
$ x=var
$ eval $x=another_value
$ echo $var
another_value
I recommend you this doc before using eval : http://mywiki.wooledge.org/BashFAQ/048
And a safer approach is to use declare instead of eval:
declare "$x=another_value"
Thanks to chepner 2 for the latest.
It sounds like you want $HOME/myfile to support Bash notations, such as parameter-expansion. I think the best way to do that is to modify $HOME/myfile to be, in essence, a Bash script:
export a=$b/c/d/e
and use the source builtin to run it as part of the current Bash script:
source $HOME/myfile
... commands ...
cp myOtherFile "$a"
... commands ...
try this
cp myOtherFile `echo $a`

Resources