Reputation: 61
I want to understand how to write nested escape sequences in sh
. I have to need illustrated by an example, I want to write something like this
sh -c sh -c sh -c sh -c sh -c date
Expected Output: current date
I tried the following, could go upto 2 levels of nesting but lost:
sh -c date
Sat May 2 18:38:38 PDT 2015
sh -c "sh -c date"
Sat May 2 18:38:43 PDT 2015
sh -c "sh -c \"sh -c date\""
Unmatched ".
I want a general purpose way to escape like the 5 levels of nesting shown above.
Upvotes: 2
Views: 472
Reputation: 295288
Unlike POSIX sh, bash
provides an explicit way to ask the shell to escape data to be eval-safe, with printf %q
.
Thus, with bash:
$ command_str=date
$ nest() { printf 'sh -c %q\n' "$1"; }
$ nest "$command_str"
sh -c date
$ nest "$(nest "$command_str")"
sh -c sh\ -c\ date
$ nest "$(nest "$(nest "$command_str")" )"
sh -c sh\ -c\ sh\\\ -c\\\ date
...and so on, ad infinitum.
In POSIX sh, the third-party library Push can be used for that same purpose:
$ source push.sh
$ command_str=date
$ Push -c command_str sh -c "$command_str"; echo "$command_str"
sh -c date
$ Push -c command_str sh -c "$command_str"; echo "$command_str"
sh -c 'sh -c date'
$ Push -c command_str sh -c "$command_str"; echo "$command_str"
sh -c 'sh -c '\''sh -c date'\'
$ Push -c command_str sh -c "$command_str"; echo "$command_str"
sh -c 'sh -c '\''sh -c '\''\'\'\''sh -c date'\''\'\'
...etc.
If you wanted to automate the nesting for an arbitrary number of levels:
nest() {
local cmd_str level >/dev/null 2>&1 ||: "in POSIX sh, local may not exist"
level=$1; shift
## in bash
printf -v cmd_str '%q ' sh -c "$@"; cmd_str=${cmd_str%" "}
## in POSIX sh, using https://github.com/vaeth/push
#Push -c cmd_str sh -c "$@"
if [ "$level" -gt 1 ]; then
nest "$((level - 1))" "$cmd_str"
else
printf '%s\n' "$cmd_str"
fi
}
Then:
nest 5 date
...would give you (with printf %q
, vs push)...
sh -c sh\ -c\ sh\\\ -c\\\ date
Upvotes: 3
Reputation: 738
assuming this is what you meant...
sh -c "sh -c \"sh -c \\\" sh -c \\\\\\\" sh -c \\\\\\\\\\\\\\\" date \\\\\\\\\\\\\\\" \\\\\\\" \\\" \" "
This gets pretty ugly, and honestly I'm not sure why you'd ever want to do this, but hey, there it is. Nest away!
Upvotes: 2