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

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!

Related

How to continue with nested for loops with a "zsh: no matches found" error? [duplicate]

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!

How to make alias compatible with links?

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

using glob to substitute a variable

After reading some docs from globs in bash
https://mywiki.wooledge.org/glob#extglob
I´m struggling to replace a part of a variable:
Just an example that i am using to learn a bit more
myvar="value1=aaa value2=bbb value3=ccc value4=ddd"
value2="zzz"
myvar="${myvar//value2=*([a-z0-9-])/value2=${value2}}"
result:
echo $myvar
value1=aaa value2=zzz
expected result:
echo $myvar
value1=aaa value2=zzz value3=ccc value4=ddd
The result of the code above is not the expected one as it´s deleting everything behind value2=bbb in myvar.
If I use:
shopt -s extglob
it is working from a virtual machine with linux but from my current machine is not even if the begining of the script starts with #!/bin/bash. Most probably because i´m not using bash in my terminal.
Any other way to achieve this? (with sed for example without enabling extglob)
thx
If you really can't use Bash, then you can maybe do what you want with lowest common denominator shell features like this:
pre=${myvar%%value2=*}
post=${myvar#"$pre"value2=}
v2=${post%%[!a-z0-9-]*}
post=${post#"$v2"}
myvar="${pre}value2=${value2}${post}"

Zsh: Is there a way to show the line and source location of a function (similar to Bash's extdebug)?

In Bash, if you do:
shopt extdebug
declare -F some_function
It will print out not only the source of the function, but also what file it's located in and what line it starts on, looking something like: some_function 339 /Users/nate/.bash/functions
However, I can't seem to find any equivalent in ZSH. Is it possible without to do without grepping?
The reason being, using third-party libs, a function could be coming from anywhere, and it's incredibly handy in tracking down issues if one of those functions is overwriting a builtin.
Hopefully it's just that my google-fu is weak.
Thanks :)

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