Package: zsh Version: 4.3.0-dev-5-1 Severity: normal
it is fiendishly difficult to write a portable shell version of xargs that can take a shell function as an argument and that follows good programming practices involving reentrance, namespaces, signals, exit codes, etc. what i would propose, if i thought that both the bash and zsh development teams would be interested in them, would be about 10 improvements, including a portable built in xargs and xargs -0 from the get-go. but i will limit my ambitions and propose a truly raw read -r. this is because i think that both teams would want that. here is why this is important. consider: find ... -xdev | grep -v \\.svn/ | xargs ... grep apple xargs is bad for this because grep cannot print the filename properly. you could use xargs and call $0, but that's inefficient and doesn't handle non-exported variables. you might think that a shell loop can achieve the same effect, but consider what many people will do: find ... -xdev | grep -v \\.svn/ | while read -r i do grep apple "$i" done this will not get all filenames. read -r does not do a raw read -- to see what i mean try leading whitespace in the input. there are other problems with it also, such as it being difficult to know how to do the equivalent of xargs -0. it gets complicated to fix unless you hit on the IFS idea, and even then it is fiendish wrt reentrance etc. lots of people probably do their backups using such a loop. my IFS solution works for me, but i think that the user shouldn't have to figure out that it is necessary or do comprehensive testing. imho there should be an xargs/xargs -0 built into both zsh and bash to make it maximally easy, but a good start would be a truly raw read. below is my solution and comments. all of my shell code has to work in both bash and zsh. ====== # #IFS='' works in bash but it fails as \\\ -> \\ in zsh readvari () { #use this instead of read or read -r #or if not too slow: while . $0 readvari IFS=$'\n' read -r "$1" } mapcar () { mapcarhow normal "$@" ;} gather () { mapcarhow gather "$@" ;} mapcarnospace () { mapcarhow nospace "$@" ;} mapcarhow () { local how="${1:?}"; shift #will local work? local mchargs='' #if you do mapcar aaaaa where aaaaa does another mapcar to dev null #it works whether the following local is declared or not #local readspecialspecial while readvari readspecialspecial do case $how in nospace) "$@""$readspecialspecial" ;; normal) "$@" "$readspecialspecial" ;; gather) mchargs="$mchargs \"$readspecialspecial\"" ;; esac done case $how in gather) eval "$@"$mchargs ;; esac } #this can do xmapcar mapcarawk () { #!this works perfectly but is even slower than below awk '{c="'"$@"'" " " "'\''" $0 "'\''" ; system(c)}' } readraw () { #read one line and print it, returning nonzero for EOF #head -1 does not exit nonzero for EOF. line #works but cat ... | mapcar is different from mapcar #awk 'BEGIN { s="" ; a=getline s ; if (a) print s ; exit 1-a }' #line works with ^D but read does not, at least when called by mapcar1. # IFS=$'\n' read -r # #zsh and bash # echo -E "$REPLY" } # #read -d `echo -e '\0'` # #and IFS='\0' read ... do not work. # #IFS='\0\0\0' read seems not to work. # #mawk might not be able to do this # awk 'BEGIN { RS="\000" ... #works but has offensive inband code. designed for while mapcar1 ...: #still has problems: maybe some weird filenames, and it stops on error (which #is ironic and sucky given bash's tendency to continue on ^C) #mapcar1 () { # #there seem to be several bugs in the shells that prevent this from being # #easy. test cannot compare to a string with \n easily, read isn't # #portable, bash cannot do local a=`readraw || r=1` or even local # #a=`readraw || return 1`, read -r is not truly raw in either bash or # #zsh. `...` cannot set variables since it is apparently a subshell. # #etc. this also makes xmapcar difficult. # # # #maybe while # #readraw > $one-line-tmp-file would work, but ... the file system? # # #even this seems not to work: # #local line=`readraw` # #local r=$? # #if [ "$r" = 0 ] # #then # #fi # #return $r # # local gensym=/dev/null/special--nonexistent--mapcar1 # #readraw prints \n on EOF, so we compare to this # local kludge=`echocode "\n$gensym"` # local a=`readraw || echo -n $gensym` # if [ "$a" = "$kludge" ] # then # return 1 # else # mapcarinside "$a" "$@" # fi #} ====== thanks. -- System Information: Debian Release: 3.1 Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6 Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968) Versions of packages zsh depends on: ii debconf [debconf-2.0] 1.4.30.13 Debian configuration management sy ii libc6 2.3.6-7 GNU C Library: Shared libraries ii libncurses5 5.5-1.1 Shared libraries for terminal hand Versions of packages zsh recommends: ii libcap1 1:1.10-14 support for getting/setting POSIX. ii libpcre3 4.5-1.2sarge1 Perl 5 Compatible Regular Expressi -- debconf information: * zsh/rcmove: -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]