Hot answers tagged

23

Your confusion stems from the fact that many popular languages (especially C-based ones) stop evaluating && sequences when 0 is encountered, because 0 is considered false and everything else is true. In Bash, however, that's not the case. By convention, in POSIX systems (and all other Unix-like systems), return code 0 is considered SUCCESS (there was ...


19

zsh like most modern shells have a choice between two different keyboard mappings for command-line editing: a vi one and an emacs one. In some shells (like tcsh or readline-based ones like bash), the emacs one is the default and probably the one you expect. With zsh, you get emacs mode by default unless $EDITOR or $VISUAL contains vi (if you're a ...


18

Virtually all shell arrays (Bourne, csh, tcsh, fish, rc, es, yash) start at 1. ksh is the only exception that I know (bash just copied ksh). Most interpreted languages at the time (early 90s): awk, tcl at least, and tools typically used from the shell (cut -f1-3, head -n 3, sort -k1,3, cal 1 2015, comm -1) start at 1. sed, ed, vi number their lines from ...


16

It's not /usr/bin/[ in either of the shells. In Bash, you're using the built-in test/[ command, and similarly in zsh. The difference is that zsh also has an = expansion: =foo expands to the path to the foo executable. That means == is treated as trying to find a command called = in your PATH. Since that command doesn't exist, you get the error zsh: = not ...


14

Oooh, I found an explanation. To quote the relevant part: The zsh shell comes with (more than one) great feature(s), such as remote tabcompletion. If you for example want to copy a file over scp, simply hit tab at any part of the filename on the remote host. zsh is able to establish an ssh session on the background, and fetch the related information ...


14

You could put a shell wrapper around a call to python (put this in .zshrc or .bashrc... depending on your shell), python () { if [ "$1" = manage.py ]; then command python manage.py && xyz else command python "$@" fi } But I suspect you are better off changing manage.py to run xyz at the end (see python subprocess ...


9

This is very well known problem which is even described in zsh manual under chapter ALIASING (see man zshmisc). The recomended way of dealing with it is to use function instead of alias: foo() { ls; } ; foo or even better in case of ls: foo() { ls -- "${@:-.}"; } ; foo ps. semicolon at the end of the function definition (list) and spaces are not ...


9

You can not do it. Because aliases were expanded only after history expansion and entire line was read in one go, so when foo was executed, the alias expansion process was gone, it's too late for the shell to recognize new alias. The best way you can do is defining alias in .zshrc or using function like jimmij's answer or using eval: alias foo=ls; eval ...


9

ksh93 has disciplines which are typically used for this kind of thing. With zsh, you could hijack the dynamic named directory feature: Define for instance: zsh_directory_name() { case $1 in (n) case $2 in (incr) reply=($((++incr))) esac esac } And then you can use ~[incr] to get an incremented $incr each time: $ echo ~[incr] ...


8

The purpose of ${1+"$@"} for portability. POSIX defined $@ would expand to nothing if there're no positional arguments. But original Bourne shell (/bin/sh in Solaris 10 and before) would expand it to empty string "". Using ${1+"$@"} is a work around for this, since when "$@" only expanded if $1 was set. Unfortunately, this construct doesn't work in zsh 3.x ...


8

The return value from commands are different from typical boolan values. 0 is success when executing a command, anything else is failure. && expects 0 to me success here for that reason.


8

When you press Ctrl+Z in a terminal, this causes the foreground process group to receive the signal SIGTSTP (assuming the terminal is in cooked mode and the default key bindings are in place). If the process hasn't set a signal handler for SIGTSTP, this causes the process to be suspended (and even if the process has set a signal handler, it usually only does ...


8

The old-fashioned way was to use POSTEDIT POSTEDIT=$'\e[0m' (and by the way this isn't bash, don't use a DEBUG trap to simulate preexec: zsh is where it's from) but since zsh 4.3.11 you can use the command line syntax highlighting facility. Let your prompt care only about your prompt and set zle_highlight=(default:bold)


8

Use $^array. It turns the array into a sort of brace expansion of the array. As in when a=(foo bar baz), $^a would be a bit like {foo,bar,baz}. $ a=(foo bar baz) $ echo prefix${^a}suffix prefixfoosuffix prefixbarsuffix prefixbazsuffix For multiplexing arrays: $ a=(1 2 3) b=(a b c) $ echo $^a$^b 1a 1b 1c 2a 2b 2c 3a 3b 3c Naturally, if the prefix or ...


7

With zsh, use glob qualifiers: mv home*(.) dst moves only regular files. While mv home*(^/) dst moves files of any type except directories. mv home*(^-/) dst would also exclude symlinks to directories.


7

You can combine parameter expansion with brace expansion. % foo=(d e f) $ echo {a,b,c}${^foo} ad bd cd ae be ce af bf cf If you don't want to define foo separately (as seems likely), you can use the following: $ echo {a,b,c}${^:-d e f} ad bd cd ae be ce af bf cf If you have the rcexpandparam option set, then you don't need the ^ in either example to ...


7

This seems to be from prezto defining a function overriding diff. It may well have a way of disabling that, but I don't know what it is. You have a few options: /usr/bin/diff or command diff will both run the diff command, rather than the function. unset -f diff will remove the diff function. You could put that in your shell configuration. As you've found, ...


7

I think the most plausible answer to this is the reverse array built-in from zsh If you have an array with 4 elements, lets say myvar=(1 2 3 4) and you want to access the 4th element it will be print $myvar[4], right? However, if you want to create a loop that will list the elements inside this array backwards, it's just a matter of using negative indexes: ...


6

Both are wrong with the zsh default option settings. You can easily see what's going on by using echo as the command instead of mv. Interactively, it looks like you have the null_glob option set. According to the zsh documentation that option is not set by default. What happens with that option unset depends on whether another option, nomatch, is set or ...


6

Having a global keybind to disown the foreground process is impossible: Keystrokes are received by the foreground process, not by the shell. You need to first suspend it with Ctrl+z if you want to disown it. However, turns out there's a zsh option to speed up disowning then continuing: With setopt AUTO_CONTINUE, disown will automatically also send SIGCONT. ...


6

zsh -o SOURCE_TRACE From the zsh manual (zshoptions(1)): SOURCE_TRACE If set, zsh will print an informational message announcing the name of each file it loads.  The format of the output is similar to that for the XTRACE option, with the message <sourcetrace>.  A file may be loaded by the shell itself when it starts up and shuts ...


6

By default the only environment variable that's transmitted over an SSH connection is TERM. You can pack information there but you've got to be sure that it'll be unpacked on the server side. The client can transmit other messages, but the server needs to be set up to accept them with an AcceptEnv directive in /etc/sshd_config. Under Debian and most ...


6

What you want is preexec hook function: preexec() { printf "\e[0m"; } Then before each command was executed, preexec will be run to reset your font to normal. So, to get the same prompt you show in your question, add these lines to your ~/.zshrc: autoload -U colors && colors PS1="%{$fg_bold[yellow]%}%n@%m %{$fg[blue]%}%~ \$ ...


6

You can just remove .pdf to get the file's name without the extension and check for a file of that name with the .xoj extension: for f in *.pdf do if [ -f "${f%.pdf}".xoj ] then xournal "${f%.pdf}".xoj & else xournal "${f}" & fi done


6

!(pattern) is ksh glob syntax, in zsh, you use ^(pattern) to negate the matching when extendedglob enabled: setopt extendedglob print -rl -- ^(2test|3test) If you want to use ksh syntax, you need to enable kshglob: setopt kshglob print -rl -- !(2test|3test) You can also use the and-not/except operator: setopt extendedglob print -rl -- *test~[23]* ...


6

When you use setopt extendedglob you can use ^(2test|3test) to remove all files except 2test and 3test: # setopt extendedglob # touch {1..10}test # rm ^(2test|3test) # ls 2test 3test ! is used by bash, zsh however uses ^.


6

for i in {01..20}; do #replace with your own range echo \ wp input csv "MyCSV$i.csv" directory_name done Comment out the echo line if it gives you the results you want. zsh, which you tagged your question with, has a shorter form: for i (MyCSV{01..20}.csv) wp input csv $i directory_name Or you could use its zargs function: autoload zargs # best ...


6

When you want aliases to have parameters you can use functions, e.g. $ gpdo () { git branch -d "$1" && git push --delete origin "$1" } Then you can do gpdo branch_name This is also useful for multiple commands although they can also be done with an alias with multiple &&s if there are no parameters and no conditional logic, looping, ...


6

“Process suspended with Ctrl+Z” is actually a subset of “suspended process that's a child of this shell”, and it's easier to track: that means there's a suspended background job. In zsh, you can check the jobstates array. echo There are ${#jobstates:#suspended:*} suspended jobs In bash or zsh, jobs -s lists only suspended jobs. echo There are $(jobs -s ...


5

Sub shell might be useful. func() {(set -e echo a ehco b echo c )} func func func This script produces: a script.sh: line 3: ehco: command not found a script.sh: line 3: ehco: command not found a script.sh: line 3: ehco: command not found Alternatively you might be interested in this try/catch implemetation in bash.



Only top voted, non community-wiki answers of a minimum length are eligible