I am trying to send this query to my command line:
docker exec cardano-node sh -c 'echo {
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}
> /tmp/payment.skey '
The issue with this command is that it is malformed and I need to wrap the JSON in quotes, but single quotes are already being used by the parent command. I don't have access to change the JSON. How can I escape some of the quotes or change this query to pass this command to my docker container?
CodePudding user response:
If Your Container Uses Bash
Let the shell do the quoting for you. If the copy of sh you're dealing with is provided by bash (the easiest case) and your host has bash 5.0 or newer, that looks like:
json='{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}'
docker exec cardano-node bash -c "echo ${json@Q} >/tmp/payment.skey"
...or, compatible with older versions of bash, you can ship a function into the container:
writeFile() { cat >/tmp/payment.skey <<'EOF'
{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}
EOF
}
docker-exec cardano-node sh -c "$(declare -f writeFile); writeFile"
Without Bash: Feeding Data Through Stdin
Without requiring bash, you can take advantage of stdin being plumbed through, to do the echo
outside the container:
docker exec -i cardano-node sh -c 'cat >/tmp/payment.skey' <<'EOF'
{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}
EOF
...or, equivalently...
echo '{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}' | docker exec -i cardano-node sh -c 'cat >/tmp/payment.skey'
Using Bash Extensions Only On The Host
You can put single quotes inside a single-quoted string using $''
, as follows:
docker exec cardano-node sh -c $'echo \'{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}\' >/tmp/payment.skey'
CodePudding user response:
You can put single quotes inside single quotes in bash:
sh -c $'echo \'{ "foo": "bar" }\''
However, it's much easier to store it in variable and echo that:
json='{ "foo": "bar" }'
sh -c "echo '$json'"
But it's generally better to feed the commands through the shell's stdin, so:
echo "echo '$json'" | sh
Or use cat
to output the stdin inside sh
:
echo "$json" | sh -c cat
If the JSON is inside a file, it's even easier:
sh -c cat < file.json
If you need to use a big string, you can use a heredoc instead:
sh -c 'cat' <<EOF
{ "foo": "bar" }
EOF
So your command would be:
docker exec cardano-node sh -c 'cat > /tmp/payment.skey' <<EOF
{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}
EOF
But there's probably no need to use sh
, since you can use tee
to write to the file:
docker exec cardano-node tee /tmp/payment.skey
But that would output to stdout, if you don't want to see the output:
docker exec cardano-node tee /tmp/payment.skey > /dev/null
So your final command would be:
docker exec cardano-node tee /tmp/payment.skey > /dev/null <<EOF
{
"type": "PaymentExtendedSigningKeyShelley_ed25519_bip32",
"description": "Payment Signing Key",
"cborHex": "xxxxx"
}
EOF