0

I am using tar --transform over SSH call to rename the documents during archiving based on array DOCUMENTNAMES.

    tar -uvf /tmp/$TARGET''TVL_document.tgz'' --transform='s|'\${doc}'|'\$docname'|' -C /appl-doc/a-mc-acc-dms/DATA \${doc}

I am able to get the tar output if DOCUMENTNAMES contain no space (e.g. "application.pdf"). For DOCUMENTNAMES with spaces (e.g. "project form.pdf"), the shell does not expand it correctly and I get the error tar invalid transform expression

How can I escape the --transform='s|'\${doc}'|'\$docname'|' sequence in a way that spaces in DOCUMENTNAMES get escaped correctly?

Full code:

DOCUMENTNAMES=("project form.pdf" "application.pdf")

# SSH to Linux fileshare to create tar
sshpass -p $IPA_PASS ssh -tt -o StrictHostKeyChecking=no $IPA_NAME@$TARGET "sudo su - jboss <<'EOF'

# create an empty tar
tar -cvf /tmp/$TARGET''TVL_document.tgz'' -T /dev/null

# transfer local array to remote
eval `typeset -p DOCUMENTNAMES`

index=0
for doc in "${DOCUMENTIDS[@]}"
do  
    docname=\${DOCUMENTNAMES[\$index]}

    # Update tar with one document at a time and update name using transform
    tar -uvf /tmp/$TARGET''TVL_document.tgz'' --transform='s|'\${doc}'|'\$docname'|' -C /appl-doc/a-mc-acc-dms/DATA \${doc}
    index=$((index+1))
done
EOF
"
2
  • Why can't you just make a script, copy it to the remote server and run it, instead of trying to figure out the hellish quoting of heredocs, shells, shells over ssh, etc.?
    – muru
    Commented Apr 10, 2022 at 12:15
  • ungh... in /tmp/$TARGET''TVL_document.tgz'', the single quotes seem a bit unnecessary do anything, that should probably be "/tmp/${TARGET}TVL_document.tgz", though I'm not sure if you need a slash there in the middle. I'm also not sure what the point of the quoting in --transform='s|'\${doc}'|'\$docname'|' is. And well, as for that script, are you really sure you want to pass a here-doc on the SSH command line? Instead of just having the here-doc in the script here? The way it's now, it looks to me that the first double quote in "${DOCUMENTIDS[@]}" ends the quoted string.
    – ilkkachu
    Commented Apr 10, 2022 at 12:16

1 Answer 1

1

Looks like you want:

DOCUMENTNAMES=("project form.pdf" "application.pdf")

# never pass password on the command line. Here passing it via an env var
# instead
SSHPASS=$IPA_PASS sshpass -e \
  ssh -o StrictHostKeyChecking=no "$IPA_NAME@$TARGET" '
    sudo -Hu jboss bash' << EOF

# pass variables across by dumping their definition on the client shell
# into the code interpreted by the remote shell
$(typeset -p TARGET DOCUMENTNAMES DOCUMENTIDS)

# rest in a heredoc with quoted delimiter so no expansion happens.
$(cat << 'END_OF_SCRIPT'

# never put files with fixed name in world writable directories
# here using a ~/tmp dir instead. You could also use things like:
# tmpdir=$(mktemp -d) || exit
tmpdir=~/tmp
tarfile=$tmpdir/${TARGET}TVL_document.tgz

mkdir -m 700 -p ~/tmp || exit
# create an empty tar
tar -cvf "$tarfile" -T /dev/null

index=0
for doc in "${DOCUMENTIDS[@]}"
do  
  docname=${DOCUMENTNAMES[index]}

  tar -uvf "$tarfile" --transform="s|$doc|$docname|" -C /appl-doc/a-mc-acc-dms/DATA "$doc"
  (( index++ ))
done
END_OF_SCRIPT
)
EOF

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .