help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Help-bash] script with ssh and filenames with spaces


From: Greg Wooledge
Subject: Re: [Help-bash] script with ssh and filenames with spaces
Date: Thu, 18 Jul 2013 08:59:11 -0400
User-agent: Mutt/1.4.2.3i

On Thu, Jul 18, 2013 at 10:31:49PM +1000, Matthew Cengia wrote:
> The OP stored the ls arguments (including the filename with its space)
> in an array, and the array expansion isn't happening correctly:

Yes, but did he do that because that's part of the problem, or because
he thought it was part of the solution?

>   address@hidden:tmp$ lsargs=(-l -a -r -t "dir with spaces")
>   address@hidden:tmp$ ssh toto <<EOF
>   ls "address@hidden"
>   EOF

The issue with dynamically generated code being issued on the remote
system is that ssh invokes a shell which does *another* parsing of the
code.  So you need to anti-parse the code manually, in such a way that
it executes as desired when you go through not just one, but two layers
of shell parsing (the local script, and the remote shell).

This is why it would be better to put the code directly in the here
document instead of generating it at run time, if that's at all possible.
It skips this whole double parsing fiasco.

If you MUST generate the code dynamically (not yet a proven assertion!)
then you need to be aware of a few things:

1) Bash's printf has a %q operator which does anti-parsing.  That is, it
   generates a string which when evaluated by Bash reproduces the original
   string.  It can be used as the "opposite of eval", or in this case,
   as the "opposite of remote shell parsing".

2) The output of %q may use syntax that only Bash can handle.  Therefore
   the remote shell must be Bash, not sh or ksh or csh or tcsh or zsh or
   whatever.  Bash.

3) When you put "address@hidden" in a here document (with unquoted delimiter),
   the array is expanded, but the quotes are treated literally.  It doesn't
   work like you would expect "address@hidden" to work outside of a here
   document context.  Fortunately, we don't need the word separation that
   "address@hidden" would normally do.  The concept of word separation would
   not be meaningful anyway, because we're generating a stream of data that
   we intend to be parsed by a remote shell, not a list of words within
   a programming environment.

Thus:

imadev:~$ args=(-ld "/tmp/foo bar")
imadev:~$ qargs=(); while read -r -d ''; do qargs+=("$REPLY"); done < <(printf 
'%q\0' "address@hidden")
imadev:~$ ssh vandev bash <<EOF
> ls address@hidden
> EOF
address@hidden's password: 
drwxr-xr-x   2 wooledg    pgmr            96 Jul 18 08:35 /tmp/foo bar

I stress once again that this runtime generation of parseable shell code
is an extremely touchy thing, and should be avoided if at all possible.
The issues here are exactly the same as the issues involved when you use
"eval".  Hopefully you already know to handle every single character of
your code like it's radioactive waste when eval is involved.  The same
issues apply here.

(Portability note: the += assignment operator requires Bash 3.1 or
higher.  If you're working with older versions, keep an index variable
and increment it.)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]