|
|
#1 |
|
Guest
Posts: n/a
|
How to get this to work in zsh?
Hello all, I've been playing with a snippet of code to remove non-existent directories from my path. This incarnation of the incantation is by mervTormel:
pwrangle () # march thru path elements removing non-existent ones { local dlist=$PATH local p="" local IFS=": " for x in $dlist; do if [ -d $x ] ; then p=$p:$x ; fi done export PATH="${HOME}/bin${p}" ; } Now, when I do this in bash (having set -xv to see what's going on), $PATH is separated out into individual directories which are then tested (the '-x' part). However, when running 'pwrangle' in zsh, the entire $PATH is tested all at once. What gives? |
|
|
|
#2 |
|
Triple-A Player
Join Date: Aug 2002
Location: Germany
Posts: 108
|
Try using $path instead of $PATH, that should work.
$PATH has the paths seperated by colons, $path is the array of paths. But it seems that the zshguide even contains an example for what you would like to do (http://zsh.sunsite.dk/Guide/zshguide02.html#l24 ) Thanks to macosxhints for showing me the error of my ways (tcsh)... Alex |
|
|
|
|
|
#3 |
|
Guest
Posts: n/a
|
Thanks for replying, below. It had been a while since I'd looked at that section of the zsh guide. However, what it's talking about is removing duplicates from your path. Actually, I had already included
typeset -U path cdpath manpath fpath in my .zshenv. What that pwrangle function does is remove directories that don't exist from the path. Also, I'm trying to figure out why bash will strip the colon from $PATH and check each directory, but zsh doesn't. (I guess fundamentla differences between shells.) Using $path does seem to get me closer to what I'm trying to do, but there's still an error about not being able to set the path when I do so. Any other ideas? Thanks. |
|
|
|
#4 |
|
Major Leaguer
Join Date: Jan 2002
Location: Adelaide, South Australia
Posts: 470
|
Here's something that seems to work, but I'll not be vouching for the programming style. (Local versus global variables rah rah). In any case, it might give you some ideas about how to implement it in a neater way. (zsh synchronises $path and $PATH, though as pointed out above, they're different beasts. So you can manipulate either one of them, as in the mish-mash below!)
newpath=(); for dir in $path; do if [[ -d $dir ]]; then newpath=( $newpath $dir ) fi done export PATH=${(j.:.)newpath} Cheers, Paul |
|
|
|
|
|
#5 |
|
Guest
Posts: n/a
|
Thanks, pmccann. The double bracket thingy [[ -d $dir]] vs. the original single bracket [ -d $x ] along with using $path in the beginning and $PATH at the end seems to have gotten it. Now off to the manpages to see just what the differences are between [[ ]] and [ ], and also to research that last little bit (j.:.)
|
|
|
|
#6 |
|
Triple-A Player
Join Date: Aug 2002
Location: Germany
Posts: 108
|
No need to look:
... tests in sh used a single pair of brackets, ... The Korn shell was deliberately made to be different, and zsh follows that. The reason is that `[[' is treated specially, which allows the shell to do some extra checks and allows more natural syntax. For example, ... in sh it's dangerous to test a parameter which may be empty: `[ $var = foo ]' will fail if $var is empty, because in that case the word is missed out and the shell never knows it was supposed to be there; with `[[ ... ]]', this is quite safe because the shell is aware there's a word before the `=', even if it's empty. Also, you can use `&&' and `||' to mean logical `and' and `or', ... Actually, zsh provides the old form of test for backward compatibility, but things will work a lot more smoothly if you don't use it. Taken from the zshguide So the bottom line is: In zsh, use [[..]] for all your testing needs. I forget this often enough... ![]() Alex |
|
|
|
|
|
#7 | |||||||||||||||||||
|
Triple-A Player
Join Date: Feb 2003
Location: back in t'ol' smoke :(
Posts: 225
|
so are we saying zsh is a better bet? as someone who is about to go headlong into getting to grips with one or another shell, it would be nice to know what everyone reckons to be 'the best'.
__________________
JKP. |
|||||||||||||||||||
|
|
|
|
|
#8 |
|
Triple-A Player
Join Date: Aug 2002
Location: Germany
Posts: 108
|
"we" are indeed saying zsh is the better bet.
zsh IMHO has the best of all worlds, allows you to do more, with less hassle. There might be a little learning curve involved, but where isn't... Alex |
|
|
|
|
|
#9 |
|
All Star
Join Date: Jan 2002
Posts: 534
|
ditto what below said about zsh. It's the best shell IMHO.
|
|
|
|
|
|
#10 |
|
Guest
Posts: n/a
|
Thanks below, that's some Good Stuff®. jkp23, zsh is a great interactive shell. You can do things like
ls -ld *(/) to list only directories or ls **/*.dmg to recursively find all .dmg files. Now, no one likes a preachy zsh user so I'll say that bash and tcsh are pretty good interactive shells (although they don't have as many bells and whistles as zsh). As far as programming/script writing is concerned, zsh is maybe a bit TOO configurable. You may have to take into account that other users might be using options that would mess up your script, and need to unset those options in your script. I chose zsh over tcsh because it's in the sh family (why learn a csh related shell like tcsh for interactive use and an sh shell for scripting?). I chose zsh over bash because I'm too lazy to do all that typing. (zsh gives you all kinds of command completion).
|
|
|
|
#11 |
|
Major Leaguer
Join Date: Jan 2002
Location: Adelaide, South Australia
Posts: 470
|
Ah well, since noone else has popped this bit of info into the discussion...
export PATH=${(j.:.)newpath} just joins ("j") the newpath array using the ":" string in order to return a nice scalar (as required for PATH). Very cute. Cheers, Paul (who likes threads to be self-contained so that when the same thing comes up again I won't have to be scratching my spartan noggin about the j.:. thing for too long) |
|
|
|
|
|
#12 |
|
Guest
Posts: n/a
|
Thanks Paul!
|
|
|
|
#13 |
|
Prospect
Join Date: Sep 2002
Posts: 4
|
IFS expansion in zsh
In zsh, IFS expansion doesn't occur unless you have set the SH_WORD_SPLIT option. Alternatively, you could use ${=PATH} to cause IFS expansion for the variable PATH but leave the shell environment alone.
example: $a=w:x:y:z $cat $a cat: w:x:y:z: No such file or directory $cat ${=a} cat: w: No such file or directory cat: x: No such file or directory cat: y: No such file or directory cat: z: No such file or directory |
|
|
|
![]() |
|
|