How to make alias compatible with links? - bash

I am trying to make a bash script that recognizes specific links from a text file, then sends a command that replaces a specific string in a different file with a image link.
This is what I have right now.
#!/bin/bash
alias https://www.examplelink.com='sed -i -e "/replacen_next_line/s/\".*\"/\"https://www.exampleimage.com\"/" to/image/replace.txt';
cd /to/link/file/example;
. ./filewithlink.txt;
I get this message whenever executed
./filewithlink.txt: https://www.examplelink.com: not found
The script works fine without links. So I assume special characters is the reason it isn't working. Not sure if this is necessary information but these are all the special characters used in the links :/._-?=

Deep in the dungeons of the bash manuals, there is the remark:
Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt (see the description of shopt under SHELL BUILTIN COMMANDS below).
Because you source the script, you might create a function instead of an alias.
Or, if that is not to your liking,
shopt -s expand_aliases

Related

Is there a ZSH equivalent to "shopt -s nullglob"?

I'm currently working on a script that deletes all the PNG files from my Desktop. I want to create an array of file paths then use the rm command on each one.
This is the relevant bit of code:
#!/usr/bin/env bash
shopt -s nullglob
files=("$HOME"/Desktop/*.png)
files_found="${#files[#]}"
shopt -u nullglob
It has been recommend that I use shopt in case of no matching files.
However I'm on MacOS and just discovered that shopt is not available for ZSH. When I run the script I get command not found: shopt.
I've found the ZSH has an equivalent called setopt however after reading through the documentation I can't quite figure out which option is the correct one to use in the case. I can't seem to find any examples either.
Can anyone point me in the right direction?
The corresponding option in zsh is CSH_NULL_GLOB (documented in man zshoptions).b
setopt CSH_NULL_GLOB
(As far as I can tell, the idea of a pattern disappearing rather than being treated literally comes from csh.)
The more zsh-like approach is not to set this as a general option (as suggested in the answer given by chepner), but to decide on each pattern, whether or you want to have the nullglob effect. For example,
for f in x*y*(N)
do
echo $f
done
simply skips the loop if there are no files matching the pattern.
Just come to the realisation that the issue of shopt not being found was due to me auto-loading the file as a ZSH function.
The script worked perfectly when I ran it like so:
bash ./tidy-desktop
Previously I had been running it just with the command tidy-desktop
Instead I now have this in my zsh_aliases:
tidy-desktop="~/.zshfn/tidy-desktop"
Thanks to #Charles Duffy for helping me figure out what was going on there!

Uppercased command aliasing in bash script?

I have a script I'm trying to make at least somewhat platform-independent. Because I can't count on the PATHs or shell aliases of my users (some of whom have been known to create aliases matching "reserved words" meaningful to the shell), I've taken to aliasing all non-builtin shell commands with uppercase equivalents. This works fine when I do it semi-manually, e.g.
AWK=/usr/bin/awk
DATE=/bin/date
GREP=/bin/grep
, but not so well when I try it in a function by iterating through an array of commands:
createAliases() {
COMMANDS=(awk chmod date echo git mkdir)
WHICH=/usr/bin/which
for command in ${COMMANDS[#]}; do
${command^^}=$($WHICH ${command})
done
}
, which produces errors like AWK=/usr/bin/awk: No such file or directory. Is my attempt to use the string^^ up-casing mechanism interfering with the variable assignment? It looks like the shell is actually trying to run the (aliased) commands, which is not what I want.
Any assistance is appreciated!
The following seems to work:
shopt -s expand_aliases
createAliases() {
COMMANDS=(awk chmod date echo git mkdir)
WHICH=/usr/bin/which
for command in ${COMMANDS[#]}; do
alias ${command^^}=$($WHICH ${command})
done
}
Prefixing the assigment with alias actually registers the desired aliases.
The line shopt -s expand_aliases enables you to then use these alias from anywhere in the script, according to https://www.thegeekdiary.com/how-to-make-alias-command-work-in-bash-script-or-bashrc-file/

Utilizing Bash Completion in a script

I have a script which takes a UUID as the argument. When I run it manually I can access it using custom tab completion I have written. Is there a way of accessing this completion in a shell script?
~/myscript stop 0011<tab>
It will complete to:
~/myscript stop 0011-1111-1111-1111
Edit:
For example:
#!/bin/bash
echo "~/myscript stop \t" | bash -i
The bash completion is already written. I'm currently executing it in another interactive shell, is there a way of executing this is the same shell?
I'm not sure why you can't just put the full UUID into your script. But I expect that you can do what you want to do using the bash compgen builtin.
I haven't played with compgen much and I've never used custom tab completion, so I can't give you detailed instructions, but using compgen to generate a list of possible filename completions is easy enough.
Eg, in my home directory,
compgen -f .ba
prints
.bash_history
.bashrc.dpkg-old
.bashrc
.bash_logout
.bashrc~

Alternative for aliases to be seen inside shell scripts

I have set inside .bashrc some aliases that I need to be seen inside a shell script I can't modify.
So, as long as I can't expand the aliases inside that script, what alternative do I have?
(For example, I need to define python2.6 to be the same as python)
Define and export functions instead of using aliases.
Let's say your script uses mv without -i or -v and you want to add them, but can't modify the script.
function mv () { command mv -iv "$#"; }
export -f mv
Now your script will use those options. You can define the function from the command line or in a wrapper script.
The Bash manual says: "For almost every purpose, shell functions are preferred over aliases."
Well written scripts use absolute paths to executables (e.g. /bin/mv). Doing so will prevent this technique from working and is good security practice.
If you can wrap the script, you can define aliases in the wrapper and source (. /path/to/script) the script. Both functions and aliases should work that way.
If you can't, you have to put the commands in PATH. Either as symlinks or as scripts.
Bash functions are more versatile than aliases, and can serve the same purpose.
There is a shell option to expand aliases: shopt -s expand_aliases, however it is switched off for a reason - aliaises in shell scripts are a support nightmare. The alternative is to use the full command, and recommended.

bash tab completion without variable expansion?

Let's say I have these variables defined in my bashrc:
i='cgi-bin/internal';
e='cgi-bin/external';
f='cgi-bin/foo';
b='cgi-bin/bar';
ad='cgi-bin/admin';
#etc...
When I use the variable on the command line vim $i/edit_TAB it will expand the variable and the input on the command line becomes vim /www/productX/subdomain_x/cgi-bin/internal/edit_ (respective to whatever site I'm on) and then I TABTAB to get the possible completions.
That's fine, the functionality isn't the problem. It's just that it can get annoying to see the full path every time rather than just the value of the variable.
Is there a way to not expand the bash variables on the command line without compromising functionality?
Is it the bash completion that's doing this?
The desired outcome would be $i not expanding to it's value (visually) or $i expanding to a relative path rather than the full path.
You might try using zsh instead of bash. In zsh,
vim $i[tab]
expands $i to a relative path
(Also Oh My Zsh is great for customizing zsh)
I am not sure which other settings you use in your bash startup scripts, but for me the following bash command does the trick:
complete -r -v
shopt -u direxpand
-u: Disable (unset) shell optional behavior flag
direxpand:
If set, Bash replaces directory names with the results of word expansion when performing filename completion. This changes the contents of the readline editing buffer. If not set, Bash attempts to preserve what the user typed.
Check current status with shopt direxpand (or all options with shopt).
Re-enable with shopt -s direxpand
Soure:
https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
Using
shopt -u progcomp
worked for me, after this the tab did not expand variables anymore.
A shopt doc
https://www.gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html

Resources