Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: why is eval needed?



2022-11-20 08:27:01 -0800, Ray Andrews:
> 
> On 2022-11-20 07:08, Stephane Chazelas wrote:
> > zsh doesn't impose anything. "-L 2" is a string made of 4
> > characters in any shell or programming language. There's no
> > programming language where "-L 2" means 2 strings -L and 2.
> 
> But that's the thing, I'd naively thought the variable could be inserted in
> the command string and be 'just' a string of characters, but zsh imposes
> that 'tree' must see '-L 2' as a single entity, yes?

No, you have it completely backwards. And I think at the heart
of your misunderstanding there is the misconception that you
pass a "command string" to an executable.

You do not, you pass a list of arguments.

On Unix-like systems, execution of commands are with the execve()
system call which takes 3 arguments:

1. the path name to the executable
2. a list of arguments: argv[]
3. a list of environment variables: envp[]

What is commonly refered to as a command line is the shell's
interface to that system call.

VAR1=foo VAR2=bar cmd 'arg 1' arg2

Is how you tell your shell to do a

execve("/path/to/cmd", ["cmd", "arg 1", "arg2"],
[exportedvariable, "VAR1=foo", "VAR2=bar"])


You do not pass the "cmd 'arg 1' arg2" string as argument to
/path/to/cmd.

>  As shown, we need word
> splitting to solve the problem and show tree what it wants to see. Or, as I
> was speculating, some way of just flattening the string back to nothing more
> than a string of characters -- but then again, probably tree wouldn't like
> that either, perhaps the string is always 'packaged' into words?  If so,
> then there's no avoiding that we must word-split '-L 2' into two words and
> there's nothing to wish for.

Why store those two arguments as a string with a space in between them
and then ask the shell to split it, that makes no sense.

Just store those two arguments and pass them to tree, that's exactly
what arrays are for. In several shells like rc or fish, all variables
are arrays (also in csh, but csh has many other issues of its own).
From a design point of view, that's the most sensible thing to do as
what shells deal with primarily is the list of arguments to commands¹

zsh: args=(-L 1); tree $args
rc: args=(-L 1); tree $args
fish: set args -L 1; tree $args
tcsh: set args = (-L 1); tree $args:q
ksh: set -A args -- -L 1; tree "${args[@]}"
ksh93/bash2+(/zsh): args=(-L 1); tree "${args[@]}"

(¹ a complication and a spanner in the works is that environment
variables (those VAR=value strings passed in envp[] above) are
string/scalar only; in csh and in the Bourne shell, shell variables and
env variables were more separated than they are in modern shells).

If you wish

arg='-L 2'
tree $arg

passed "-L" and "2" as separate arguments to tree, do you also wish
that:

file='my file.txt'
rm -- $file

Also passed "my" and "file.txt" as separate arguments to rm for rm to
unlink those 2 files?

What about:

files=(
  'my file.txt'
  'my other file.txt'
)
rm -- $files

Should they be split too?

How about:

text='shutdown|reboot'
echo $text

Should that run echo shutdown|reboot and reboot?


[...]
> > Calls tree with "-L" and "1" as arguments is not that bash
> > doesn't do some sort of magic "grouping" that zsh would be
> > doing, but that ksh/bash contrary to zsh does that extra layer
> > of $IFS-splitting from the Bourne shell on top of the syntax
> > parsing as the default value of $IFS happens to contain the
> > space character.
> Ah!  So my little issue is a zsh exclusive?

No, again, any recent shell (i.e. post 1980) that had no intention of
being compatible with the Bourne shell including rc (and derivatives
like akanga or es) and fish behave like zsh in this instance².

In fish,

set arg '-L 1'
tree $arg

Or in rc/es/akanga:

arg = '-L 1'
tree $arg

all call tree with one "-L 1" argument.

(² and even better, zsh still has that issue that unquoted expansions to
empty removal, one of the issues with Bourne-like shells that it hasn't
fixed. rc/es/akanga/fish have).

>  Not complaining tho, I don't
> like zsh doing things I didn't ask it to do so if in this case I need to
> request a word split that's just fine.  After all it's tree that's being
> difficult so the problem is rare and easily solved.

No, it's not tree being difficult. In any command doing

cmd '-o arg'

is passing the " arg" string as argument to the -o option.

sort '-o file' file

Will sort the "file" file into the " file" file just like you asked. If
you want to sort it into itself, it's sort -o file file

[...]
> > nm is a standard development command (though not -D which AFAIK
> > is a GNU extension). Part of GNU binutils on GNU systems.
> Ah, that's why I can't find it.  It's hard to find commands so packaged.

apt-file is your friend.

For the POSIX standard (2018 edition) see
https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/

[...]
> > Again, tree has nothing to do with the GNU project.
> 
> I dunno, I get it all from Debian and Debian is a GNU/Linux OS so I don't
> know more than that.

On Debian

dpkg -S =tree

Will tell you what package the tree command comes from.

apt showsrc that-package

Will tell you how it was built and generally where the source came from.
Here, not from gnu.org but from http://mama.indstate.edu/users/ice/tree/
http://mama.indstate.edu/users/ice/tree/changes.html shows it has a long
history and might be even as old as zsh.

-- 
Stephane




Messages sorted by: Reverse Date, Date, Thread, Author