/r/zsh

Photograph via snooOG

What is /r/zsh about?

Zsh is a shell designed for interactive use, although it is also a powerful scripting language.

Before asking questions...

Please check on the zshwiki.org FAQ and the official FAQ before asking questions.

If your script behaves strange, please check it with shellcheck - it is made for bash scripts but also works with zsh for the most part.

Learning resources can be found in our wiki.

What does zsh different from bash/ksh/...?

  • zsh completion is fast, interactive and shows the meanings of flags
  • highly customizeable
  • automatically parses files for different commands (known_hosts for ssh, services for systemctl, ...)
  • right-hand prompt
  • fuzzy directory/file completion
  • suffix aliases
  • ... much more

Read zsh FAQ Chapter 02 for more info.

Related subreddits

/r/commandline
/r/bash

/r/zsh

19,116 Subscribers

0

Copilot-like CLI suggestions as an extension to the zsh-autosuggestions plugin.

1 Comment
2024/11/02
10:56 UTC

4

zsh-abbr 6 coming soon. heads up for those with advanced setups still using deprecated things

Been pushing towards the zsh-abbr v6 major version release. I expect only a small minority of users will have to do anything to migrate — the breaking changes are dropping internal things already deprecated in current v5. But just in case: migration guide at https://v6.zsh-abbr.olets.dev/migrating-between-versions.html#upgrading-from-v5-to-v6, and pointers for pinning your major install to 5.x at https://v5.zsh-abbr.olets.dev/installation.html

0 Comments
2024/11/01
21:42 UTC

2

Is my zsh broken?

Hello everyone,

I think my zsh is either broken or that I simply don't understand it quite well :)

When I for example paste this:

sudo systemctl enable --now syncthing@<username>.service

I am met with the following in the shell:

sudo syssudo systemctl--now syncthing@<usernam<>.servic>

But all the text is white except:
sudo systemctl which is green.

It for some reason adds and changes a few things.

And if I press m I see the suggestion mdadm -AsfR && vgchange -ay but when I press TAB (which I pressume is "give me the suggestion" I get mMACHTYPMACHTYPE=

Is it supposed to work like this or is something broken?

Sorry for no images, just get errors when I add it in the post.

5 Comments
2024/10/31
15:37 UTC

3

when looking up associate array key by value, how best to handle value parse errors?

[Edit: solved https://www.reddit.com/r/zsh/comments/1gg10jp/comment/lum5vh1/ ]

I'm using ${(k)hash[(r)val]} to look up keys by values in an associative array hash.

% typeset -A hash=( [a]=b )
% val=b
% echo ${(k)hash[(r)$val]}
a # good
% val=c
% echo ${(k)hash[(r)$val]}
% # good

and ran into this problem:

% val=')'
% echo ${(k)hash[(r)$val]}
% b # bad

I'm guessing that it's related to

% )
zsh: parse error near `)'

I've found that I can guard against the false find by first checking whether the needle is one of the hash's values

% val=')'
% (( ${${(v)hash}[(Ie)$val]} )) && echo ${(k)hash[(r)$val]}
% # good

Anyone have a better way?

Fwiw my real use case is slightly different: my array has heavily-quoted values, ( ['"a"']='"b"' ), and I'm really doing (( ${${(v)hash}[(Ie)${(qqq)val}]} )) && echo ${(k)hash[(r)${(qqq)val}]}

4 Comments
2024/10/30
23:49 UTC

0

npx command not found when executed from custom function

I have a basic custom function that wraps some NPM commands when in a particular repo:

function unittests() {
  local path=$PWD;
  local argc="$#"; #arg count
  local argv=("$@"); #arg value
  local modules; #modules to run

  printf -v modules "A/B/%s," "${argv[@]}"
  modules=${modules%,}

  if [[ $path == "$HOME/code/my-cool-repo" ]]; then
    if [[ $argc != 0 ]]; then
      npx cross-env ... # run tests for modules, obfuscated for brevity
    else
      echo "Running tests for my-module...";
      npx cross-env ... # run tests for modules, obfuscated for brevity
    fi;
  else
    echo "Not currently in ../my-cool-repo; aborting..."
    return 1;
  fi;
}

This was working in bash no issue. I migrated to ZSH a few days ago and I get an error when running it: command not found: npx.

I use NVM and source it (using below command) from my .zshrc and can verify npm is loaded with command like npm --version, npx --version, etc. It's definitely there.

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

This is my PATH: export PATH="/opt/homebrew/bin:$PATH"

Any clue what the issue could be?

I'm not sure what info would be relevant, so if I need to provide more please let me know.

Thanks!

6 Comments
2024/10/29
20:37 UTC

0

zsh: example: command not found...

Hi,

I keep my binaries and scripts in ~/.local/bin, but whenever I add something new to it, Zsh can't find it, and I get a "command not found" error. After a reboot, it works as expected.

I've looked through several articles, but most only cover setting the PATH variable. Maybe I'm missing something in my configuration. Any help would be appreciated. Thanks!

1 Comment
2024/10/29
13:09 UTC

17

Navita - A new Frecency based Directory Jumper

20 Comments
2024/10/28
16:56 UTC

1

how to move words ignoring WORDCHARS?

I've bound ctrl arrows to move between words, but in zsh4humans you could also press ctrl shift arrows and to move by entire words and alt shift backspace to remove entire words including words in quotes as if WORDCHARS weren't set. Is this part of some zsh module or was it zsh4humans exclusive feature? I've tried reimplementing it (code) and failed spectacularly

WORDCHARS='*?[]~&;!#$%^(){}<>,|=+'

bindkey '^[[1;5D' backward-word  # Ctrl + Left Arrow
bindkey '^[[1;5C' forward-word   # Ctrl + Right Arrow
3 Comments
2024/10/28
01:07 UTC

2

Creating a copy output to clipboard command

copy -x

- copies last x commands and their outputs in the terminal to the clipboard

I dont know much about shell scripting, I asked chatgpt to do this, but it could only copy the last x inputs (but not the outputs)

thank you. (terminal - default terminal on macOS)

5 Comments
2024/10/26
14:08 UTC

0

KISS way to manage your configs with zsh

# config management
declare -x -A configs
configs=(
    astronvim       "$XDG_CONFIG_HOME/astronvim/"
    fish            "$XDG_CONFIG_HOME/fish/config.fish"
    gdb             "$XDG_CONFIG_HOME/gdb/gdbinit"
    git             "$XDG_CONFIG_HOME/git/config"
    helix           "$XDG_CONFIG_HOME/helix/config.toml"
    hx              "$XDG_CONFIG_HOME/helix/config.toml"
    irssi           "$HOME/.irssi"
    lazyvim         "$XDG_CONFIG_HOME/lazyvim/"
    lvim            "$XDG_CONFIG_HOME/lvim/config.lua"
    nu              "$XDG_CONFIG_HOME/nushell"
    nvim            "$XDG_CONFIG_HOME/nvim"
    ohmy            "$HOME/.oh-my-zsh"
    readline        "$HOME/.inputrc"
    tridactyl       "$XDG_CONFIG_HOME/tridactyl/tridactylrc"
    vim             "$HOME/.vimrc"
    wezterm         "$XDG_CONFIG_HOME/wezterm"
    xmake           "./.xmake/linux/x86_64/xmake.conf"
    zsh             "$HOME/.zshrc"
    ideavim         "$HOME/.ideavimrc"
)
for key value in ${(kv)configs}; do
    eval "function ${key}config {
    if [[ $key == \"zsh\" ]]; then
        command \${@:-\$EDITOR} $value && source $value && echo ${configs[zsh]} has been sourced
    else
        command \${@:-\$EDITOR} $value
    fi
}"
done

Now you can modify your ~/.zshrc with zshconfig and it will source it

You can also pass a editor as argument. Try gdbconfig nano for example.

I have been relying on this for quite some time and thought I'd share the good word

12 Comments
2024/10/25
13:27 UTC

0

End of line looks broken

Hi, i was configuring Oh my zsh, powerlevel10k and all the other cool customizations on the zsh but at some point i broke what i would guess is the end line of my neo vim editor, and now looks like this. Does anyone knows where could i edit that ? Thank you very much.

https://preview.redd.it/ev44y3qorvwd1.png?width=1526&format=png&auto=webp&s=cc57c6a1cf794579f2c85bbd64117b2e35f0f746

2 Comments
2024/10/25
10:35 UTC

1

Colorful output for some keywords

Hello Community,

I currently use ZSH and Starship as current setup and always wanted to know if you can color certain words in specific colors whenever they appear. As a network consultant I often use SSH connection to networks devices and want for example color the word "down" or "notconnected" in red.

Do you have any idea on how to do that?

MobaXTerm on Windows has something built-in.

https://preview.redd.it/yne8knawuowd1.png?width=776&format=png&auto=webp&s=819c506d47611adfd260f4d23eda766b04a2e96e

12 Comments
2024/10/24
10:38 UTC

2

[HELP] Home, delete, etc keys on zsh

So this problem has been driving me crazy for months. zsh just doesn't know how to handle basic keyboard input. You can go in and bind them specifically, but then if you go from terminal A to terminal B, or open tmux or screen, then suddenly it shits the bed and can't handle the keys again. I assumed this was a bug. But based on this thread I just found:

https://old.reddit.com/r/zsh/comments/1cpmzzb/help_what_is_happening_to_my_keybinds/?ref=share&ref_source=link

This is actually the intended behavior? Is that correct? You're supposed to figure out how to bind basic keyboard yourself in every different terminal/environment?

6 Comments
2024/10/23
18:30 UTC

15

Optimizing ZSH Performance with OMZ Features

Hello,

I'm new to ZSH and appreciate the autocompletion and robbyrussel theme offered by Oh My Zsh (OMZ). However, I've noticed that OMZ can be slower on my system compared to Fish and Bash + Starship.

For context, I'm switching away from Fish due to its cumbersome SSH experience and Bash because of its limited autocompletion feature. Is there a way to use OMZ-like features without the performance overhead?

In summary, I'd like to configure my ZSH to have similar functionality and appearance to OMZ, but I'm not sure where to begin.

14 Comments
2024/10/19
04:14 UTC

4

Missing plugin from move to new mac

So I had a mac for like 4 years and I had set up oh-myzsh in all likelihood. However I got a new mac and I can't seem to find out how to get it back to the way it was.

Previously if I start typing in terminal, then hit tab it would jump to a previous command with that text, and I could keep hitting tab to cycle through previous commands.

e.g. I could type: py then hit tab and it might bring back:

python3 runfile.py

since it was the last command in my history that matches.

Any idea if this was a plugin? I have lost my ,zhrc file.

Thanks

2 Comments
2024/10/18
16:41 UTC

1

oh-my-zsh fzf-plugin does not heed FZF_DEFAULT_COMMAND

Hi! When using mv **<Tab> A lot of unrelated entries pop up (e.g. .wine-subfolders which in turn contain all! mounted drives). I wanted to get rid of this and added these paths to the ignore-file of fd (which is used by fzf).

This works fine as long as I call fzf directly in the console. However if I use the **-syntax (like above), the output is as before (including these paths). I also tried to export some garbage FZF_DEFAULT_COMMAND, but again this did not change the **-behavior. So somehow the export is not taken into account.

in my .zshrc the relevant lines are export FZF_DEFAULT_COMMAND='fd --type f' plugins=(fzf) source $ZSH/oh-my-zsh.sh

So this should be in the right order, echo $FZF_DEFAULT_COMMAND in a new shell also outputs what is set in the .zshrc.

Any idea why this happens or how I can debug it? Thank you :)

1 Comment
2024/10/18
15:14 UTC

1

Starship.rs question that's not in the FAQ or docs

hey folks -

At the start of the default toml config I see this:

Get editor completions based on the config schema

"$schema" = 'https://starship.rs/config-schema.json'

The JSON looks like a preconfigured bunch of settings. What is this doing?

2 Comments
2024/10/18
13:09 UTC

1

cpu_arch not showing up on powerlevel10k prompt

3 Comments
2024/10/17
11:01 UTC

2

Missing Alias

I have an alias set to change "docker" to "DOCKER_DEFAULT_PLATFORM=linux/amd64 docker-compose build" from a year ago when I was working a lot with docker.

I dont want that alias to exist anymore. but I cant find it.

I posted my initial help ticket in  yesterday, whose comments I reference below. here is the post.

https://www.reddit.com/r/bash/comments/1g2yth1/comment/lrsolob/?context=3

Here is what i've done to find and diagnose the issue:

  1. tried all terminal searches recommended by the brilliant minds of this sub (thank you all, seriously)

1a. tried every other possible search technique recommended by chatgpt (desperate, learned a lot)

  1. disabled all potential 3rd party app culprits

  2. booted into safe mode (this stopped the text replacement)

  3. created and used a new user account on my mac (this also stopped the text replacement)

  4. checked in system settings -> keyboard -> text replacement (obviously, not in there.)

  5. tried using keyboard maestro (my normal text replacement strategy) to cancel it with the inverse replacement, which didn't work, because my system seems to be pasting it instead of typing the string, so KM doesn't recognize the trigger string

that tells me that the action lives somewhere in my main users home folder. What I don't understand, is why the search term "docker" or "DOCKER_DEFAULT_PLATFORM=linux/amd64 docker-compose build" return no results. I have no listed aliases other than the main two that boot with macOS (run-help=man which-command=whence)

I am beginning to think this is an issue compounded from macOS software updates since I set it up. how is it possible that there is no executable file or defined alias that returns the culprit, but the text replacement still works? I can hardly get it to work under ideal conditions!

seriously spinning my head at this one. if there are any wizards out there who can help me tackle this issue, I will be forever grateful.

15 Comments
2024/10/14
16:49 UTC

2

Expanding an array to a string with the entries quoted

say i have an array with entries that may contain spaces:

arr=(foo bar 'with space' baz)

what is the best way to turn this into:

"foo bar 'with space' baz"

any help is appreciated!

3 Comments
2024/10/10
20:11 UTC

2

Help with function

Hello everybody. I am trying to have two things execute when I run `pihole` in my CLI. Obviously I have the actual IP address instead of the brackets.

This is in my .zshrc file:

"""

alias pihole2='ssh -L 8888:localhost:80 pi@[ip address]’

function pihole {

  # Uses the alias

  pihole2 & 

  # Open the PiHole admin page

  open http://localhost:8889/admin

}

"""

Whenever I type `pihole` in my terminal, it successfully does the ssh connection, but it doesn't open the browser. Am I doing something wrong? Can someone help me please?

I am using MacOS

10 Comments
2024/10/10
01:48 UTC

0

Problem with iTerm Terminal and Powerlevel10k Theme configuration

Hello everyone!
I'm having trouble configuring Powerlevel10k Theme inside my iTerm terminal on my Macbook Pro. I'll start by saying that it's a fairly old Macbook, a mid-2014 model with MacOS Big Sur 11.7.10.

What I would like to get as a configuration is this:

https://preview.redd.it/w5ibo59dyitd1.png?width=1544&format=png&auto=webp&s=7422a15aeadc2e1d18bd2d47838fbbd9fd642344

The main problem is that during the configuration of Powerlevel10k I don't see some customization choice that I see are there in the tutorials. I'm pretty sure I've done all the various steps correctly. I installed oh-my-zsh as well as Git and Homebrew but it still doesn't work as I would.
Why do you think I can't configure, for example, the icon before the tilde or the prompt separators?
What I'm getting after the configuration of Powerlevel10k is this:

https://preview.redd.it/ll57btxdyitd1.png?width=1250&format=png&auto=webp&s=ad942b9db7a5a1c7484035708f82d26dd3e3cae8

Thank you for all the explanation!

3 Comments
2024/10/08
12:17 UTC

0

Do stuff getting eval'd only change on plugin updates?

Caching e.g. eval calls is nothing new (smartcache is a simple implementation), but I'm wondering if the stuff that typically gets eval'd in people's configs only change on plugin or system package updates. If so, the cache should get refreshed when they are updated.

But besides that, are there any other reasons the cache should be refreshed and/or certain things that shouldn't be cached? Obviously if what gets evald changes on every shell invocation then it wouldn't benefit from caching.

1 Comment
2024/10/08
03:35 UTC

1

Simple backreference problem

I have an array of plugins:

local -Ua ZPLUGS=(
  zsh-users/zsh-autosuggestions
  zsh-users/zsh-completions
  ...
)

plug-clone $ZPLUGS

plug-clone iterates over the array to ensure the plugins are cloned. They have the naming scheme ~/.cache/zsh/zsh-autosuggestions--zsh-users (~/.cache/zsh/<plugin>--<plugin_repo>).

plug-clone function:

local repo plugdir=$XDG_CACHE_HOME/zsh
local -Ua repodir

# Convert plugins to their expected repo dirs
for repodir in ${${@:-$ZPLUGS}:/(#b)([^\/]#)\/(*)/$plugdir/$match[2]--$match[1]}; do

  if [[ ! -d $repodir ]]; then
    # Convert back to <plugin>/<plugin_repo> naming scheme for git clone
    repo=${repodir:/(#b)(*)\/(*)--(*)}$match[3]/$match[2]
    echo "Cloning $repo..."
    (
      git clone -q --depth 1 --no-single-branch  --recursive --shallow-submodules \
        https://github.com/$repo $repodir &&
      zcomp $repodir/**/*(.DN)
    ) &

  fi
done
wait

Now I want to add branch support to the repos, e.g.:

local -Ua ZPLUGS=(
 # Clone the repo, switch to the dev branch
  zsh-users/zsh-autosuggestions:dev
)

But I'm stumped on how to get backreferencing to match the optional :dev after an item in the array for the dev branch. Or maybe zsh-users/zsh-autosuggestions branch:dev implementation, whatever makes more sense or is simpler (I don't want quotes to be necessary though, e.g. "zsh-users/zsh-autosuggestions branch:dev" for an item of the array.

Also I'm pretty sure I don't need have backreferencing twice in the code.

Any help is much appreciated, new to Zsh.

2 Comments
2024/10/06
22:09 UTC

1

Weird behavior with file descriptor redirection

So, at some point while working on a project for an OS course, I was required to create a file descriptor with number 99 and assign it to a file, like this: exec 99> file However, zsh returns: zsh: unknown command: 99 And exits with code 127

The weird thing is, it works perfectly with a one-digit fd, say 9. Also, bash has no problem whatsoever with the two-digit fd. I also tried executing the command with zsh -f and it still doesn't work, so it probably isn't caused by my plugins.

ChatGPT insists that zsh imposes a limit on up to 9 file descriptors per process, but I can't find anything similar on the internet.

Is there really such a limit on file descriptors? Can I somehow increase it? Is there any other solution to get problem?

Note: ulimit -n returns 1024 allowed fds by the system

4 Comments
2024/10/06
12:32 UTC

3

zsh does not load completions form site-functions

Hi,

I use zsh and oh-my-zsh on my Ubuntu 24.04. The .zshrc is created by oh-my-zsh init script. I only added these line to enable auto-completion.

autoload -Uz compinit && compinit
zstyle ':completion::complete:*' use-cache 1

I found lots of the packages I want to use, such as eza and distrobox, provided completion support for both bash and zsh. However, I don't get completion for them in zsh. If I jump to a bash shell, I got the completions.

But for what I remember, zsh completion definitions in the site-functions folder should be loaded by default, right? But it feels like only some of them are loaded, e.g. I have completion for rsync and docker commands.

14 Comments
2024/10/06
00:30 UTC

2

Undo last autocompletion in zsh with backspace

Does anybody know how can I revert last autocompletion (let's say pressing tab when writing ls ~/) to delete the autocompleted subdirectory with backspace?
if required this is my .zshrc: https://github.com/glabka/configs/blob/master/home/.zshrc
Any idea or source is welcomed.

7 Comments
2024/10/05
20:31 UTC

27

I'm writing my own config for zsh. What features in zsh are the most important for you

30 Comments
2024/10/04
09:57 UTC

1

zsh-autocomplete is not working properly

Hello..
I wanted to setup zsh autocomplete for my mac terminal..

So, I have been using WezTerm.

After that I install zsh-autocomplete using homebrew and edited my .zshrc to source the zsh-autocomplete and restarted the terminal.

now.. when I want to do cd to a directory.. it's not showing me the names of directories and all.. I dont know what I am doing wrong.

Below is my .zshrc file. Can anyone please tell me what I am doing wrong?

# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

source /opt/homebrew/share/powerlevel10k/powerlevel10k.zsh-theme
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

# history setup
HISTFILE=$HOME/.zhistory
SAVEHIST=1000
HISTSIZE=999
setopt share_history
setopt hist_expire_dups_first
setopt hist_ignore_dups
setopt hist_verify

# completion using arrow keys (based on history)
bindkey '^[[A' history-search-backward
bindkey '^[[B' history-search-forward

# Source other plugins
source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh
source /opt/homebrew/opt/zsh-fast-syntax-highlighting/share/zsh-fast-syntax-highlighting/fast-syntax-highlighting.plugin.zsh
source /opt/homebrew/share/zsh-autocomplete/zsh-autocomplete.plugin.zsh

# ---- Eza (better ls) -----
alias ls="eza --icons=always"

# ---- Zoxide (better cd) ----
eval "$(zoxide init zsh)"
alias cd="z"

# Conda initialization
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"
__conda_setup="$('/opt/homebrew/Caskroom/miniforge/base/bin/conda' 'shell.zsh' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/opt/homebrew/Caskroom/miniforge/base/etc/profile.d/conda.sh" ]; then
        . "/opt/homebrew/Caskroom/miniforge/base/etc/profile.d/conda.sh"
    else
        export PATH="/opt/homebrew/Caskroom/miniforge/base/bin:$PATH"
    fi
fi
unset __conda_setup

# FZF initialization
source <(fzf --zsh)

Solution : https://www.reddit.com/r/zsh/comments/1fvhos5/comment/lq7ijou/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button

4 Comments
2024/10/03
20:40 UTC

1

correct pwd's capitalization after cding with "wrong" capitalization on a case-insensitive file system?

I'm on macOS. It's case-insensitive file system, and cd and PWD respect that:

% cd /Users/<username> && pwd
/Users/<username>
% cd /users/<username> && pwd
/users/<username>

I'd like to force PWD's capitalization to be what it would be on a case-sensitive file system, while still supporting case-insensitive cd:

% cd /Users/<username> && pwd
/Users/<username>
% cd /users/<username> && pwd
/Users/<username> # <-- changed

I'm imagining a cdpwd hook. So far what I've thought of is a recursively building a path with (pseudocode)

case-sensitive dir name is `ls -F <parent dir name> | grep -i "^<dir name>/$"

and then cd'ing to that.

That's clunky/forky/unoptimized enough to make me say "never mind, I'll stick with the current behavior".

But maybe there's some zsh feature that would give me the case-insensitive version of the PWD, so that the hook function could be

force_pwd_capitalization() {
  add-zsh-hook -d chpwd force_pwd_capitalization
  cd $CASE_INSENSITIVE_PWD
  add-zsh-hook chpwd force_pwd_capitalization
}

or even simply

setopt force_cd_capitalization

?

9 Comments
2024/10/03
19:11 UTC

Back To Top