different behavior of which command in zsh and bash
$ zsh -c 'type which'
which is a shell builtin
$ bash -c 'type which'
which is /usr/bin/which
The solution is to not use which(1)
, which is a non-standard and not very useful command. The question of what you should use instead isn't the most straightforward due to the alternatives being poorly specified and inconsistently implemented, but they are better than which
.
Depending on your requirements, you want command
(see the -v
option), type
, or whence
. See POSIX for the former two, or your shell manual for the latter. (Bash doesn't support whence, but it is supported by most other ksh derivatives, albeit inconsistently. It typically has the most features).
different shell behaviors of unmatched glob in zsh and bash
Use setopt NONOMATCH
to leave an unmatched glob as literal text.
Similarly, use setopt NULL_GLOB
to treat an unmatched glob as if it hadn't been used at all.
Some examples:
% print recommenders[examples]
zsh: no matches found: recommenders[example]
% setopt NONOMATCH
% print recommenders[examples]
recommenders[examples]
% print recommenders[examples]
%
Both options are documented under man zshoptions
. (Use man zsh
to see what man pages are available, or man zshall
to see all of them at once.)
find command works differently in zsh and bash
Try quoting the argument, as in f 'stringBuf*'
, to avoid premature glob expansion.
If you call it unquoted, bash
will do the smart thing and, after looking for the pattern in your current directory and not finding anything, will pass the parameter to the function as is.
zsh
on the other hand, will try to match the pattern in your current directory, then complain about not finding anything, and not execute the function at all.
It is generally not a good idea to use unquoted wildcards (unless you mean it), since, if you have a file in your current directory called, say, "stringBuffoon", your parameter to f
will be turned into "stringBuffoon", and the search will not give you the results you expect.
Different rm -f behavior between bash and oh-my-zsh
zsh, by default, fails if running a command with a glob with no matches. This behavior contravenes the POSIX sh standard.
bash, by default, follows the POSIX standard, which requires passing the original glob expression to the application in question. Because rm -f
is specified to treat the case where a file already doesn't exist identically to the case where it successfully deleted that file, a glob expression with no matches is thus treated as a successful case.
To change this behavior on bash, run:
# tell bash to abort a command rather than passing it an unexpanded glob
shopt -s failglob
Different result from bash and source commands
I don't have a Mac, but here's what I can reproduce on Arch Linux (2021):
$ cat >tt.sh
listFile=("A" "B" "C" "D")
echo ${listFile[1]} ${listFile[2]}
^D
$ bash tt.sh
B C
$ zsh tt.sh
A B
When I run the script with bash, it shows B C
. When I run with zsh, it shows A B
.
Are you really using bash on the terminal you're sourcing to? You can double-check with:
$ echo $0
bash
If the above shows bash, it means you are. If it shows zsh, it means you are using zsh so you will see the zsh behaviour when you source.
Starting with macOS Catalina, the default is zsh. If you would really like the bash behaviour, you could try swiching your default shell on Mac settings.
Why does behavior of `./example` and `sh example` different? (`zsh: text file busy: ./example`)
When you do
$ ./example
you are trying to execute
"example" which is being written to. This is not allowed.
When you do
$ sh example
sh
is reading
"example", then execute what is read. This is fine.
different shell behaviour: bash omits newline, zsh keeps it
zsh
doesn't perform word-splitting on the unquoted parameter expansion $MATCH
by default. Use echo "$MATCHES" | wc -l
, and bash
should work as well.
Note this is the wrong way to iterate over the output of a command; use a while
loop and the read
command instead.
grep -ri "todo" apps/business | awk '{print $1}' | sed -e 's/://' -e 's/\#//' |
while IFS= read -r FILE; do
git blame "$FILE" | grep -i todo
done | sort -k2 | uniq
Related Topics
Mpc/Mpd on Linux: How to Play Local Wav File
Arm-Linux-Gnueabi Compiler Options
Linux Shell Kill Signal Sigkill && Kill
Re-Stream a Mpeg2 Ts Pal Stream with Crtmpserver
Docker Rootless Unable to Pull Images
Echo - Syntax Error: Bad Substitution
Prevent R from Using Virtual Memory on Unix/Linux
Ffmpeg Install on Centos 64-Bit 'Install with -Fpic' Error
How to Deal with Errno and Signal Handler in Linux
Apache 2.4.23 Undefined Reference to Crypto_Malloc_Init
How to Remove File with Special Characters
Can't Use Gpg-Agent as an Ssh Agent
Bash Command Line Arguments Passed to Sed via Ssh
How to Add a Directory to The Perl Library Path at The System Level