[Scons-users] escaping brackets () in file path

Carnë Draug carandraug+dev at gmail.com
Sat Feb 27 07:41:42 EST 2016


On 27 February 2016 at 00:19, Plunket, Tom
<tom.plunket at aristocrat-inc.com> wrote:
> It's not a direct answer to your query, but can you just quote your file
> arguments? I have to do that anyway because my users love to put spaces
> in their filenames but it also covers other shell characters pretty well.
> The only character I need to handle manually (presumably because I can't
> figure out how to get env.Literal to work) is the dollar symbol $ but that's
> because SCons tries to process it before it gets to the shell.
>

I tried it but it does not work.  The quotes become part of the argument.

    $ cat SConstruct
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    Command(target='foo (bar) qux', source=None, action="touch '$TARGET'")

    $ scons
    scons: Reading SConscript files ...
    scons: done reading SConscript files.
    scons: Building targets ...
    touch "'foo (bar) qux'"
    scons: done building targets.

    $ ls
    'foo (bar) qux'  SConstruct

Changing to quotes does not fix it either:

    $ cat SConstruct
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    Command(target='foo (bar) qux', source=None, action='touch "$TARGET"')

    $ scons
    scons: Reading SConscript files ...
    scons: done reading SConscript files.
    scons: Building targets ...
    touch ""foo (bar) qux""
    sh: 1: Syntax error: "(" unexpected
    scons: *** [foo (bar) qux] Error 2
    scons: building terminated because of errors.

I have previously bumped into similar issues where my arguments were
regular expressions and I couldn't trust SCons to quote things correctly.
This may be of help to you.  My solution at the time was the following:

    ## Add a NoShellCommand builder to be used like Command()
    ##
    ## This has the advantage that there's no shell involved, saving us
    ## from having to escape quotes, spaces, wildcards, and whatsnot.

    import subprocess
    def no_shell_command(target, source, env):
      return subprocess.call(env['action'])
    def no_shell_command_strfunc(target, source, env):
      args = env['action']
      return "$ %s " % (args[0]) + " ".join(["'%s'" % (arg) for arg in
args[1:]])
    no_shell_command_action = Action(no_shell_command,
strfunction=no_shell_command_strfunc)
    env.Append(BUILDERS={'NoShellCommand' :
Builder(action=no_shell_command_action)})

Which you can then use like this:

    NoShellCommand(source = foo, target = bar, action = [prog, foo,
bar, arg1, arg2])

Carnë


More information about the Scons-users mailing list