NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Scripting for /bin/ksh



On 08/02, Chavdar Ivanov wrote:
> On Mon, 2 Aug 2021 at 14:16, Todd Gruhn <tgruhn2%gmail.com@localhost> wrote:
> >
> > Thanks for the code Matt.
> > I will try this.
> > By 'execute' I mean generate
> > ${cmd}
> > then execute/do whatever ${cmd} turns out to be.
> 
> Depending on the contents of cmd, you might have to use
> 
> eval ${cmd}

Yes, and there's the rub: the corner cases.  To correctly build up
a command like this and execute it where spaces and other special
characters are parsed correctly, you have to shell-quote cmd before
passing it to eval.  See the "Shell-quoting arbitrary strings" section
in:

  https://www.etalabs.net/sh_tricks.html

For example, here's a test program that correctly constructs and
executes two commands, touch and ls, to create and list some
"interesting" test files:

----
#!/bin/ksh

set -e

# https://www.etalabs.net/sh_tricks.html
quote() {
  printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/"
}

# https://dwheeler.com/essays/filenames-in-shell.html
nl=$(printf '\nX')
nl=${nl%X}

f1='test_a space'
f2='test_b"double-quote'
f3="test_c'single-quote"
f4="test_d${nl}newline"
f5='test_e\backslash'

f1_quoted=$(quote "$f1")
f2_quoted=$(quote "$f2")
f3_quoted=$(quote "$f3")
f4_quoted=$(quote "$f4")
f5_quoted=$(quote "$f5")

cmd="touch $f1_quoted $f2_quoted $f3_quoted $f4_quoted $f5_quoted"
printf 'cmd: %s\n' "$cmd"
eval "$cmd"
cmd="ls -B1 $f1_quoted $f2_quoted $f3_quoted $f4_quoted $f5_quoted"
printf 'cmd: %s\n' "$cmd"
eval "$cmd"
----

Lewis


Home | Main Index | Thread Index | Old Index