bashshellechosingle-quotessshpass

bash: single quotes disappear while appending text to a file


I am trying to append a multiline text containing some single quotes(') to a file which is present on a different machine and can be only accessed through a different user. Here is my code snippet:

element_list=("element1" "element2")
for element in ${element_list[@]} 
do

read -r -d '\n' CONTENT << EOM
field1 = on
field2 = '$element'
field3 = '$element-random-text'
EOM

    CONFIG_FILE=/tmp/config.txt
    sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c 'echo \"$CONTENT\" >> $CONFIG_FILE'"

done

Though, the scripts execute successfully, the single quotes present in the field2 and field3 values disappear. The output appended to the file looks like:

field1 = on
field2 = element1
field3 = element1-random-text
field1 = on
field2 = element2
field3 = element2-random-text

I want those single quotes to dumped in the file too. Expected output:

field1 = on
field2 = 'element1'
field3 = 'element1-random-text'
field1 = on
field2 = 'element2'
field3 = 'element2-random-text'

Any help would be appreciated.

Note: There is a requirement to execute this command from a different machine and using the other_user(not the vm_user).


Solution

  • A much simpler solution is to perform all the expansion locally, and then just write the result at the end of the pipeline.

    config_file=/tmp/config.txt
    element_list=("element1" "element2")
    for element in "${element_list[@]}"
    do
        read -r -d '\n' content <<____EOM
    field1 = on
    field2 = '$element'
    field3 = '$element-random-text'
    ____EOM
        echo "$content"
    done |
    sshpass -p vm_password ssh -t vm_user@<vm-ip> "sudo su - other_user -c \"cat >> '$config_file'\""
    

    Capturing the here document only so you can then immediately echo it is obviously a waste of memory; I imagine your real loop body looks more involved.

    Don't use upper case for your private variables; see Correct Bash and shell script variable capitalization. For robustness, I also added double quotes around ${element_list[@]}; see When to wrap quotes around a shell variable