linuxbashnesteddouble-quotes

Nested double quoting in bash


I have a complex command I am trying to run inside of docker. It sets the uid of existing user, chroots into some dir, and executes a "possibly complex command there".

docker (compose with stuff) run container /bin/bash -c "setuidgid.sh a:b && exec sudo -u user1 /bin/bash -c \" mkdir -p /chrootdir/proc && cp /proc/cpuinfo /chrootdir/proc/cpuinfo && sudo chroot /chrootdir echo hi1 && /bin/bash -c \\\"echo hi2 && /bin/bash -c \\\\\\\"echo hi3\\\\\\\"\\\"\" "

I get the expected ouput here - each level of nesting strips one backslash-character pair. However the resulting command is quite ugly and difficult to read. Is there any better way to achieve this? (I have made this command specifically nested a lot, there shouldn't reach a point in my code needing more than 'hi2'. This command just for sake of question)

NOTE: I don't want to use single quotes since this innermost command will call some arbitrary command which I may not know beforehand. Can guarantee no double quotes, but single quotes may be used.

PS. any improvements to the command itself can be left in comments. Have some reasons for the current solution, and even if a tailor made solution can be figured, my main goal is to figure out how I can nest quotes for an arbitrary command. PS. I don't believe this is a duplicate, as most other questions on the topic work with nested quotes inside the substitution $().


Solution

  • As you run some inline "scripts" with sudo then it's not possible to use exported functions, but ${var@Q} (or printf %q "$var") can help make the nested quoting less error prone:

    Your original command:

    docker ... run container /bin/bash -c "
        setuidgid.sh a:b &&
        exec sudo -u user1 /bin/bash -c \"
            mkdir -p /chrootdir/proc &&
            cp /proc/cpuinfo /chrootdir/proc/cpuinfo &&
            sudo chroot /chrootdir echo hi1 &&
            /bin/bash -c \\\"
                echo hi2 &&
                /bin/bash -c \\\\\\\"
                    echo hi3
                \\\\\\\"
            \\\"
        \"
    "
    

    Recomposed command with ${var@Q}:

    sh3="
        echo hi3
    "
    sh2="
        echo hi2 &&
        /bin/bash -c ${sh3@Q}
    "
    sh1="
        mkdir -p /chrootdir/proc &&
        cp /proc/cpuinfo /chrootdir/proc/cpuinfo &&
        sudo chroot /chrootdir echo hi1 &&
        /bin/bash -c ${sh2@Q}
    "
    sh0="
        setuidgid.sh a:b &&
        exec sudo -u user1 /bin/bash -c ${sh1@Q}
    "
    
    docker ... run container /bin/bash -c "$sh0"