If I execute the following in terminal on my Macbook M1 Pro 2021 with ZSH
uglifyjs js/script.js --compress --mangle --output js/script.min.js -m reserved=['$','require','exports']
I get this error
zsh: no matches found: reserved=[$,require,exports]
But If I switch to bash then it's fine, can anyone help on this to get it fixed on ZSH?
Add quotes:
uglifyjs js/script.js --compress --mangle --output js/script.min.js \
-m "reserved=['$','require','exports']"
In both bash and zsh, square brackets are used for file globbing. The shell is attempting to find files that match the pattern reserved=[<one of these characters>]
In zsh, if there are no matches, you get an error. In bash if there are no matches, the shell silently includes the original pattern.
Which means in bash, you also want to use quotes to prevent file globbing. Otherwise, something like this can happen:
bash> echo reserved=['$','require','exports']
reserved=[$,require,exports]
bash> touch 'reserved=r'
bash> echo reserved=['$','require','exports']
reserved=r
Related
Regard this distilled example of the problem.
% echo 'echo "$((1.5*2))"' | zsh
3.
% echo 'echo "$((1.5*2))"' >x
% <x zsh
3.
% echo $SHELL
/bin/zsh
% chmod +x x
% ./x
./x: line 1: 1.5*2: syntax error: invalid arithmetic operator (error token is ".5*2")
I understand this error in bash.
If I change the script to just
echo "$SHELL"
it emits /bin/zsh as expected when executed. So I have no reason to expect bash behaviour here.
Someone explain why zsh is acting like sh/bash but identifying as zsh? I'm not interested in a work around (I have several), I want to understand this. Thanks.
Short answer: zsh is not executing the script; bash is.
$SHELL is the name of your login shell, not the currently executing shell. Unlike bash, which will use itself to execute a script with no shebang, zsh uses /bin/sh; from man zshmisc:
If execution fails because the file is not in executable format, and
the file is not a directory, it is assumed to be a shell script.
/bin/sh is spawned to execute it.
In your case, /bin/sh is a shell (either bash or dash, most likely) that does not support floating-point arithmetic.
I want to remove all files in a directory except some in UNIX. Part I desired files have a known name and for the other part, I'm using ls|grep command. But the ls | grep is working when there is only one occurrence and not when there is more than one. it is the same with find|grep. here are my commands:
rm -v !("R1.r"|"R2.r"|"r2.par"|$(ls|grep nario)|"sh.sh")
rm -v !("R1.r"|"R2.r"|"r2.par"|$(find|grep nario)|"sh.sh")
Is there any problem with my commands???
It looks like you're trying to use BASH specific extglob syntax. ls|grep won't work in the middle of the glob, because each pattern needs to be separated by a |, which won't happen with ls|grep. The easier way to do what you want is to use the shell globbing to find the files under the directory you're looking for instead. Make sure you do the following:
Are using BASH
Have extglob enabled: shopt -s extglob
Have globstar enabled: shopt -s globstar
Use file globbing rather than ls | grep
Then try again:
rm -v !("R1.r"|"R2.r"|"r2.par"|**/*nario*|"sh.sh")
Note: globstar requires BASH version 4 or higher.
I have this alias in my .zshrc file:
alias rmcons="docker rm -f $(docker ps -aq)"
But after trying to execute it, it removes only one container and then it prints
$rmcons
ef8197f147fb
zsh: command not found: c2ea2673f9e4
zsh: command not found: 4603059f1618
zsh: command not found: 40ad60328595
How can I remove all containers that docker ps -aq shows?
You need to use single quotes ('') instead of double quotes ("").
alias rmcons='docker rm -f $(docker ps -aq)'
If you use double quotes, than the command substitution $(docker ps -aq) will be evaluated when you define the alias. In your example this was equivalent to
alias rmcons="docker rm -f ef8197f147fb
c2ea2673f9e4
4603059f1618
40ad60328595"
As the newlines are command separators (like ;) this alias is substituted by four commands: docker rm -f ef8197f147fb, c2ea2673f9e4, 4603059f1618 and 40ad60328595. The last three of which do not exist on your system, hence "command not found". It also means that the same output of docker ps -aq - as it was on alias definiton - will be used and not as it would be when running the alias.
On the other hand, if you use single quotes, the alias will actually substituted by the exact command you defined: docker rm -f $(docker ps -aq). Although docker ps -aq will still return output with newlines, these newlines are now only parsed word separators between arguments.
Warning: untested. I don't use/have docker.
I think you should serialize the output first "escaping" the new lines.
You might also use the for loop, trying:
for id in `docker ps -aq`; do docker rm -f $id; done
Note the backquotes to parse the command's output.
You can also directly use $() instead of its shortcut backquote.
I recommend to test with echo first instead of removing with rm:
for id in `docker -ps -aq`; do echo rm -f $id; done
, and to use the rm with its -i switch to prompt for confirmation before deleting.
I hope docker's rm subcommand has one.
How to run zsh script in specified folder? How to specify a folder to run a script:
zsh script_name.sh
Documents said that: "-s Force shell to read commands from the standard input. If the -s flag is not present and an argument is given, the first argument is taken to be the pathname of a script to execute." but it does not work.
What is the difference between zsh -c ~/path1/ script1.sh (2 parameters) and zsh -c ~/path1/script1.sh?
You should just open a subshell, Execute the following from zsh or bash (including the parentheses):
(cd ~/path1 && source script1.sh)
Note: If your script is written for zsh, name it script1.zsh instead, since zsh syntax is not retro-compatible with old sh's.
This should work:
zsh -c "cd ~/path1 && ./script_name.sh"
I have a script that looks like this
#!/bin/bash
function something() {
echo "hello world!!"
}
something | tee logfile
I have set the execute permission on this file and when I try running the file like this
$./script.sh
it runs perfectly fine, but when I run it on the command line like this
$sh script.sh
It throws up an error. Why does this happen and what are the ways in which I can fix this.
Running it as ./script.sh will make the kernel read the first line (the shebang), and then invoke bash to interpret the script. Running it as sh script.sh uses whatever shell your system defaults sh to (on Ubuntu this is Dash, which is sh-compatible, but doesn't support some of the extra features of Bash).
You can fix it by invoking it as bash script.sh, or if it's your machine you can change /bin/sh to be bash and not whatever it is currently (usually just by symlinking it - rm /bin/sh && ln -s /bin/bash /bin/sh). Or you can just use ./script.sh instead if that's already working ;)
If your shell is indeed dash and you want to modify the script to be compatible, https://wiki.ubuntu.com/DashAsBinSh has a helpful guide to the differences. In your sample it looks like you'd just have to remove the function keyword.
if your script is at your present working directory and you issue ./script.sh, the kernel will read the shebang (first line) and execute the shell interpreter that is defined. you can also call your script.sh by specifying the path of the interpreter eg
/bin/bash myscript.sh
/bin/sh myscript.sh
/bin/ksh myscript.sh etc
By the way, you can also put your shebang like this (if you don't want to specify full path)
#!/usr/bin/env sh
sh script.sh forces the script to be executed within the sh - shell.
while simply starting it from command line uses the shell-environemnt you're in.
Please post the error message for further answers.
Random though on what the error may be:
path specified in first line /bin/bash is wrong -- maybe bash is not installed?