# Perl
exec '/usr/bin/grep', '-R', $input, 'mydir';
# PHP (with Symfony Process)
(new Process(['/usr/bin/grep', '-R', $input, 'mydir']))->run();
# Python
subprocess.run(['/usr/bin/grep', '-R', input, 'mydir'])
# C
execv("/usr/bin/grep", (char *[]) {"grep", "-R", input, "mydir", NULL});
All of these are safe in the sense that there's no risk of shell command injection (in fact, only the PHP one even calls the shell), but NONE of them are safe against this problem, where the input value might begin with a hyphen. In this grep scenario it's probably not a security issue, but it can produce confusing results for the user if nothing else. % sudo ip link set eth3 down
% sudo ip link set eth3 name "'deal-with-it'"
% sudo ip link show "'deal-with-it'"
5: 'deal-with-it': <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 10000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
The only interface-name restrictions iproute2 sets is that they can't contain NUL, slash, or white space, and they can't be longer than 15 characters. grep '^|.*PLUGH.*'
But, even with relatively simple commands, that type of completion is very limited compared to the contextual functionality that proper zsh completion functions provide. These functions know...
* Which arguments are meaningful to complete more than once — there's no reason to complete `-a` again after you've already entered `ls -a`, but an option like `-v` might be cumulative
* Which arguments are meaningful to complete in the presence of other arguments — there's no reason to complete `-A` if you've already entered `ls -a`, since those two options are exclusive
* Whether the command supports permutation — GNU tools usually do (`ls mydir/ -al`), BSD ones usually don't (`ls -al mydir/`)
* Whether options can be stacked — some commands require `-a -b -c` instead of `-abc`
* How options can be joined to their optargs — GNU supports both `--foo bar` and `--foo=bar`, curl supports only `--foo bar`, grep supports both `-m 3` and `-m3`, tree supports only `-L 3`
* How the current argument might be affected by a previous one — if you've entered `make -C mydir` it's useful to complete targets from mydir/Makefile
* How to complete multi-part arguments — if you press tab after `ssh foo@` you probably want to complete a host name or IP
* The descriptions of arguments — zsh can explain what the difference between `always` and `auto` is, and even when an argument is arbitrary, it can explain what format it takes, what the default is, what the min/max are, &c.
* Probably most importantly, the values of optargs and operands — just blindly offering file names or presenting a metavar parsed from --help (like WHEN or TYPE) is not very nice; a useful completion function will offer package names, man-page names, compression levels, PIDs, NIC addresses, or whatever else is appropriate
I know it's technically possible to do some of this with bash completion functions, but most don't, probably because the infrastructure isn't there. fish is nicer, but even it doesn't (can't?) usually go that far with it.
This level of richness (along with related UI stuff like menu selection) is why a lot of people switch to zsh even if they don't really care about its scripting features and modules and stuff. It's probably why i started using it originally.
A way to specify completion behaviour declaratively would be really cool, but if it's just going to be dumbed down to bash-like functionality, i'm not sure it's going to gain much more traction with zsh users than _gnu_generic and bashcompinit (zsh's bash-completion compatibility shim) have.