I want to run a temporary expect script with arguments and leave stdin open:
expect -c 'spawn {*}$argv' /dev/null echo hello world
However this results in
can't read "argv": no such variable
while executing
"spawn {*}$argv"
How do I execute it?
See the source code for args parsing:
656 void
657 exp_parse_argv(interp,argc,argv)
658 Tcl_Interp *interp;
659 int argc;
660 char **argv;
661 {
...
703 while ((c = getopt(argc, argv, "+b:c:dD:f:inN-v")) != EOF) {
704 switch(c) {
...
711 case 'c': /* command */
712 exp_cmdlinecmds = TRUE;
713 rc = Tcl_Eval(interp,optarg);
714 if (rc != TCL_OK) {
715 expErrorLogU(exp_cook(Tcl_GetVar(interp,"errorInfo",TCL_GLOBAL_ONLY),(int *)0));
716 expErrorLogU("\r\n");
717 }
718 break;
...
773 }
...
850 /* collect remaining args and make into argc, argv0, and argv */
851 sprintf(argc_rep,"%d",argc-optind);
852 Tcl_SetVar(interp,"argc",argc_rep,0);
853 expDiagLog("set argc %s\r\n",argc_rep);
854
855 if (exp_cmdfilename) {
856 Tcl_SetVar(interp,"argv0",exp_cmdfilename,0);
857 expDiagLog("set argv0 \"%s\"\r\n",exp_cmdfilename);
858 } else {
859 Tcl_SetVar(interp,"argv0",exp_argv0,0);
860 expDiagLog("set argv0 \"%s\"\r\n",exp_argv0);
861 }
862
863 args = Tcl_Merge(argc-optind,argv+optind);
864 expDiagLogU("set argv \"");
865 expDiagLogU(args);
866 expDiagLogU("\"\r\n");
867 Tcl_SetVar(interp,"argv",args,0);
868 Tcl_Free(args);
869
870 exp_interpret_rcfiles(interp,my_rc,sys_rc);
871 }
It runs in this order:
while
loop, -c command
(line 711) is run with Tcl_Eval()
(line 713).argc
.argv0
.argv
.So when -c command
is run, argv0/argc/argv
are not yet available.
This can also be shown with expect -d
:
$ expect -d -c 'puts "now in -c command" ' /dev/null foo bar
expect version 5.45
now in -c command <====
argv[0] = expect argv[1] = -d argv[2] = -c argv[3] = puts "now in -c command"
argv[4] = /dev/null argv[5] = foo argv[6] = bar
set argc 2 <====
set argv0 "/dev/null" <====
set argv "foo bar" <====
executing commands from command file /dev/null