📜 ⬆️ ⬇️

Switch from bash to zsh

To switch from bash to zsh, you need to know the basic differences between them - without this, it will be difficult to initialize zsh to ~/.zshrc .


I did not find a brief description of these differences when I switched myself, and I had to spend a lot of time reading the zsh documentation. I hope this article will make it easier for you to go to zsh.


Why go


For a start, is it worth spending your time and attention on the transition? To learn another sh dialect, less common than POSIX sh or bash, to re-engage in setting up the working environment ...


In my opinion, if you spend a lot of time in the console, you like Vim or Emacs and you have already spent a lot of time setting them up for yourself - definitely worth it! Zsh is very similar in spirit to them: this is a very complex and flexible program, whose capabilities are completely unknown to most, but after spending some time setting it up you can get a very comfortable working environment for you .


As for the study of the sh dialect ... the benefits of this are probably very few, but the minimum described in this article should be enough to set up zsh, and no one offers you to write new scripts in the zsh dialect. In general, this is no different from the need to minimally know VimL or Emacs Lisp exclusively for configuring Vim / Emacs.


In the internet a bunch of articles and presentations describing specific features zsh, greatly simplified someone's life. I will not list them, because everyone needs different features, and in zsh there are options for every taste. Instead, I will describe the key features of zsh that allowed these features to be implemented:



Differences and Compatibility


Once again I will clarify that I will describe exactly the differences from bash, and not the full set of zsh features. Most of the functionality you are familiar with works in zsh in the same way as in bash. But there are often zsh-specific ways to do about the same thing. This is due to the fact that zsh pays a lot of attention to compatibility with other shells, so in zsh plus their features they dragged a lot of other shells - and as a result received several alternative ways of doing the same thing.


Terms



Current settings


Many built-in commands display the current state when they are run without arguments (plus they often have an argument that draws output in the style of zsh commands, which is quite convenient).


 #   setopt #     setopt KSH_OPTION_PRINT; setopt #       bindkey #      ,    zsh for m in $(bindkey -l); bindkey -M $m -L #   (- ) zstyle zstyle -L #   (  ),    zsh alias -L #    ,    zsh alias -s -L #   () typeset #   (),    zsh typeset -p 

This is not a complete list, but for most tasks in the process of (analyzing) setting up zsh it should be enough.


It may also be useful to run zsh -f - this starts zsh in the default state (without executing any startup scripts except /etc/zshenv , which most systems don’t have).


setopt and emulate



 #         setopt nonumericglobsort setopt NO_numericglobsort setopt NO_NUMERIC_GLOB_SORT setopt _N_O_numERICglob_SORT_ unsetopt NUMERIC_GLOB_SORT unsetopt numericglobsort 

At the beginning of using zsh, for more familiar work after bash, I would recommend the following options:


 #    fd unsetopt MULTIOS #  ~…  file completion  =   setopt MAGIC_EQUAL_SUBST #   escape sequence  echo  -e setopt BSD_ECHO #      setopt INTERACTIVE_COMMENTS #  $(cmd)  $PS1 etc. setopt PROMPT_SUBST 

There is also the SH_WORD_SPLIT option, and formally, for the usual work after bash, it must also be enabled, but I would not recommend it: the behavior of zsh without this option is more convenient and logical, it is better to get used to it. It is responsible for how cmd $PARAM will work if the value of $PARAM is a string containing spaces: in bash, cmd will get several arguments, and in zsh it will take one (as if they called cmd "$PARAM" ). And if $PARAM is an array, then zsh will give cmd one argument for each non-empty element of the array (even if these elements contain spaces).


(Basically, this article describes the behavior of zsh with default options, otherwise every second sentence would have to be clarified in the style of "but with all such options, it all works differently.")


Options



Arrays



Templates



 #        , #         5   example, #     .txt ls -l **/*(<5->|example)*.txt 

Flags / Qualifiers / Modifiers


Only templates have qualifiers, they allow you to specify additional file selection criteria: by type (file / directory / symlink / etc.), Rights, time (changes / etc.), Size ... You can sort and index selected files. It is possible to include for this particular template a match of the initial * with names beginning with a dot. You can enable the removal of this template from the command line arguments if it does not match any files.


 #  5-   , #         "a", #    ls -ld *a*(D/om[1,5]) 

If you turn on the EXTENDED_GLOB option, you can use flags in templates: for files, case-sensitivity management is of interest, and if there is a match with the parameter / line, there are other useful flags.


 #    ls -ld .[cC][oO][nN][fF][iI][gG]* setopt extendedglob; ls -ld .(#i)Config* 

There are much more flags available for parameters: outputting all (including empty) array elements even in quotes, performing join or split on a given substring, outputting only keys and / or associative array values, screening with different types of quotes and inverse operation, etc.


 #       echo ${(k)some_hash} #  $PATH       ":", #          echo ${(s<:>qq)PATH} 

Both for templates and for parameters, modifiers can be used: deleting the last element of the path, deleting all elements of the path except the last, removing / leaving the extension, escaping and inverse operation, searching and replacing substrings, etc.


 #     (   #  ,       ) echo $PWD:h:t #   ( )     , #     "fil"  "FIL" (   ) echo **/*(@:t:s/fil/FIL/) 

autoload -Uz


In addition to the traditional way to load code via source /path/to/file.sh or . /path/to/file.sh . /path/to/file.sh in zsh autoloading code is actively used at the time of the first function call.


To search for a file with the desired function, $FPATH is used - a variable similar in format to $PATH , containing a list of directories in which a file with the same name as the function being loaded is searched.


When autoload called autoload no files from the disk are read, and their presence is not even checked - all this will happen when the function is first called. It is almost always necessary to autoload arguments -U to the autoload (cancels the effect of the current alias for the uploaded file, because alias often configured by the user can disrupt third-party functions) and -z (optional clarification that the uploaded file is in zsh format, but safer than always ask).


 fpath=(~/my-zsh-functions $fpath) autoload -Uz fn fn 

The contents of the ~/my-zsh-functions/fn file can be in one of these three formats:


 #   ,  - : echo "  fn" 

 #        : fn() { echo "  fn" } 

 #      ,  fn: fn() { fn2 } fn2() { echo "   fn" } echo "    fn" #       fn: fn "$@" echo "    fn" 

zkbd


When you first run zsh, it often turns out that some of the buttons like the F1 / Backspace / Delete / cursor work incorrectly. This is due to the fact that the vast majority of console applications use readline and the correct configuration of these buttons is read from /etc/inputrc and ~/.inputrc , and zsh does not.


The problem is solved in the forehead - you need to see which escape sequences issue the necessary buttons in your terminal and specify the necessary handlers for these escape sequences in ~/.zshrc . Like that:


 bindkey '^[[A' up-line-or-history # Up bindkey '^[[B' down-line-or-history # Down #  .. 

You can watch the sequences issued by the buttons by running cat >/dev/null and pressing Ctrl-V in front of the desired button. (And yet, yes, doing this in 2017 I felt a bit strange ...) But with zsh, there is a utility utility, zkbd , that automates this process. To do this, you must connect it to ~/.zshrc , after which you will have an associative $key array containing the necessary escape sequences:


 autoload -Uz zkbd [[ ! -f ~/.zkbd/$TERM-${${DISPLAY:t}:-$VENDOR-$OSTYPE} ]] && zkbd source ~/.zkbd/$TERM-${${DISPLAY:t}:-$VENDOR-$OSTYPE} [[ -n $key[Up] ]] && bindkey -- $key[Up] up-line-or-history [[ -n $key[Down] ]] && bindkey -- $key[Down] down-line-or-history #  .. 

I do not elaborate in detail which commands (such as up-line-or-history ) which buttons should be assigned because, first, you do not have to assign everything, but only those that do not work out of your box, and second, if you think As for what everyone should do, Home or Backspace all converge, here's a search in the history of Up and Down can be done in quite different ways, and the functions in these cases must also be assigned to these buttons.


(By the way, you can set the Escape character ( ^[ ) in the bindkey parameter with a real character, typing it using Ctrl-V , and two ordinary characters ^[ , and two characters \e .)


zstyle


This is a built-in way to use context-sensitive settings. It is in many ways similar to the usual parameters, except for the name and value of the zstyle parameter, zstyle allows zstyle to specify a "context" template. And then get the values ​​related to the current context. This approach is actively used to customize the work of autocompletions, but it can also be used for your scripts.


 #   my-param=default  3-  , #        (  #    zstyle,      ) #        % zstyle ':my-app:*:*' my-param default #   my-param=val-one  ,    #  ( )    "one" % zstyle ':my-app:one:*' my-param val-one #   my-param=val-two  ,    #  ( )    "two" % zstyle ':my-app:*:two' my-param val-two #   my-param   result    % zstyle -s ':my-app:a:b' my-param result % echo $result default % zstyle -s ':my-app:one:b' my-param result % echo $result val-one % zstyle -s ':my-app:a:two' my-param result % echo $result val-two % zstyle -s ':my-app:one:two' my-param result % echo $result val-one 

zmodload


Part of the additional functionality of zsh is not implemented in regular scripts loaded via autoload -Uz , but as system libraries *.so . They are used, for example, to provide access to PCRE regular expressions, math functions, sockets, etc. Such libraries are loaded via zmodload .


miscellanea


To intercept signals, in addition to the standard trap '…;code;…' INT you can use functions with special names: TRAPINT() { …;code;… } .


Many constructions like if , while , etc. there is an abbreviated form (an example is above, where the value of all bindkey modes was displayed).


Suddenly, the zsh-specific equivalent of echo — the print command — turned out to be quite handy when learning zsh. She knows a lot of things, but from the most useful:


 #      ,    print -l $path #        , #        print -a -C 2 "${(kv@)ZSH_HIGHLIGHT_STYLES}" | sort #   %-   $PS1 print -P '%Bbold%b %F{red}current%f dir is: %~' 

zsh, // Awesome- zsh .


')

Source: https://habr.com/ru/post/326580/


All Articles