win_shell/win_command chdir to Directory with Spaces

So, I’m trying to run a command via Ansible, and the command exists in a path that’s in a directory with spaces, namely c:\Program Files. I need the module to chdir to the directory where the command is actually located because there are files that it needs to reference inside that directory. Unfortunately it doesn’t seem to want to work, no matter what I try. I’ve tried the following variations on the path to make it work:
C:\Program Files\Application
C:\Program Files\Application
C:\Program\ Files\Application
C:\Program^ Files\Application
C:/Program Files/Application
C:/Program\ Files/Application

No matter what I try, here, I get the following message from the module:

The directory name is invalid

What’s the trick to making chdir work for directories with spaces??

Thanks - Nick

Nick,

I saw it mentioned somewhere that if you use ‘YAML syntax’ with the :'s instead of Ansibles ='s you should not need escape characters for directories with spaces in them. Ie, if you do it like this:

  • win_command: runsomething.exe
    args:
    chdir: c:\Program Files\Application

The other thing I can think of is adding single quotes ’ around the path.

Sadly I don’t have any Windows boxes around that I can test this on right now for you, but it could be worth a try?

Cheers, Mike

Thank you for the suggestion, Mike.

I’ve tried it both ways, and neither of them works. In fact, the “YAML Syntax” doesn’t seem to actually attempt to change directory - if I use that, I get an error along the lines of file not found or command not found, indicating that it isn’t even going to the directory. If I put it up on the line with win_command, it seems to actually try to chdir, but fails due to the space.

I forgot to mention in the original post that I have tried all sorts of variations of double and single quotes and combinations thereof, and that hasn’t made a difference - however it gets passed in to the command, it seems like PowerShell ends up interpreting it as C:\Program and just chopping it off at the space.

I am able to get a command in a directory to run using PowerShell’s special escape syntax:
& ‘C:\Program Files\Application\mycmd.exe’

But this doesn’t seem to work in the chdir argument. Unfortunately because the application that I’m running relies on the presence of certain files in the current working directory, I need to actually move to that directory.

Thanks,
Nick

I always found a bad idea to put space in files or directory names… but Microsoft did it There should be a mean to escape it correctly… But as a workaround, did you try with the 8.3 dos syntax (I hope the compatibility still exist) ? dir /x will show you what to use… (there’s a tilda in the name to use often) Regards, JYL

I think you can probably just do this using

`

chdir: ‘C:\Program Files\your path\goes\here’
`

By the way, some community members have been working on some general advice for constructing paths when dealing with windows.

Eventually the plan is to get this into the actual ansible documentation but you can read what there is at the moment here: https://github.com/ansible/community/wiki/Windows:-documentation#windows-paths or https://github.com/ansible/community/wiki/Windows-Paths---prescriptive-style

If anyone has any further feedback or examples that aren’t already covered there, please comment on the page

Hope this helps.

Jon

As others mentioned, a simple workaround is the use of short (8.3) filenames. Basically any folder (or file) with a space can be called in cmd with the 6 first characters (with spaces removed), a tilda and 1 (or 2,3, etc if other folders under the current one start with the same 6 characters). This works for me under the win_command, win_shell and ‘raw’.
E.g,
“C:\Program files” is c:\Progra~1
“C:\Program files (x86)” is c:\Progra~2
“C:\bla bla bla\a b c d e f g h i j k l m n o p” is C:\blabla~1\abcdef~1

https://superuser.com/questions/348079/how-can-i-find-the-short-path-of-a-windows-directory-file
https://en.wikipedia.org/wiki/8.3_filename

It may be easier to use the short filenames but arguably you should avoid using the short filenames as it can be a security risk. You could inadvertently run the wrong or malicious executable if someone creates a file or folder in a particular way it could change what the ~1, ~2 actually point to.

I would highly recommend you stick with quoting the paths when using win_command like so

`

  • name: run an executable inside a folder with a space
    win_command: ‘“C:\Program Files\Microsoft Windows\some-exe.exe” /argument1 “/argument 2 with space” “/argument 3 with ‘’ single quote”’

or with chdir (note: you shouldn’t have to quote the chdir arg)

  • name: run an executable with custom working dir
    win_command: some-exe.exe /argument1 “/argument 2 with space”
    args:
    chdir: C:\Program Files\Microsoft Windows
    `

It really just comes down to the fact that you should be quoting an argument with " (double quotes) to make sure it ignores spaces. In the first example, due to the YAML rules, I made sure the whole value is enclosed in ’ (single quotes) which means I only have to escape single quote instances by doubling it, e.g. ’ becomes ‘’.

The win_shell module is different as the quoting rules are dependent on the shell being used, here are some ways you can do it (note: chdir is still the same where you don’t have to quote the value if you use it

`

  • name: run an executable with a space (powershell)
    win_shell: &“C:\Program Files\Microsoft Windows\some-exe.exe” @(“/argument1”, “/argument 2 with space”)

  • name: run an executable with a space (cmd)
    win_shell: ‘“C:\Program Files\Microsoft Windows\some-exe.exe” /argument1 “/argument 2 with space”’
    args:
    executable: cmd.exe
    `

Arguably you should be using win_command if all you are doing is running an executable as that is what it is for and win_shell is used when you want to run shell commands. You can still use win_shell to run executables and as you can see from the example above the cmd one is pretty much the same as win_command but it complicates it further as Windows parses values differently in each scenario. For example, the caret symbol (^) is seen as an escape character in cmd but not the native argument parser for Windows so you would have to handle them differently depending on what module you use.

Here is a short snippet showing you what happens when using the chdir argument, I’ll use win_shell as an example but the same would apply with win_command as well.

`

  • hosts: ‘2016’
    gather_facts: no
    tasks:

  • win_shell: pwd
    args:
    chdir: C:\Program Files

  • win_shell: cd
    args:
    executable: cmd.exe
    chdir: C:\Program Files
    `

and the output

TASK [win_shell] ********************************************************************************************************************************************

task path: /Users/jborean/dev/module-tester/adhoc.yml:4

Using module file /Users/jborean/dev/ansible/lib/ansible/modules/windows/win_shell.ps1

<SERVER2016.domain.local> ESTABLISH WINRM CONNECTION FOR USER: vagrant on PORT 5986 TO SERVER2016.domain.local

EXEC (via pipeline wrapper)

changed: [SERVER2016.domain.local] => {

“attempts”: 1,

“changed”: true,

“cmd”: “pwd”,

“delta”: “0:00:00.640518”,

“end”: “2018-01-07 08:41:58.701292”,

“rc”: 0,

“start”: “2018-01-07 08:41:58.060773”,

“stderr”: “”,

“stderr_lines”: ,

“stdout”: “\r\nPath \r\n---- \r\nC:\Program Files\r\n\r\n\r\n”,

“stdout_lines”: [

“”,

"Path ",

"---- ",

“C:\Program Files”,

“”,

“”

]

}

TASK [win_shell] ********************************************************************************************************************************************

task path: /Users/jborean/dev/module-tester/adhoc.yml:8

Using module file /Users/jborean/dev/ansible/lib/ansible/modules/windows/win_shell.ps1

<SERVER2016.domain.local> ESTABLISH WINRM CONNECTION FOR USER: vagrant on PORT 5986 TO SERVER2016.domain.local

EXEC (via pipeline wrapper)

changed: [SERVER2016.domain.local] => {

“attempts”: 1,

“changed”: true,

“cmd”: “cd”,

“delta”: “0:00:00.249102”,

“end”: “2018-01-07 08:41:59.919811”,

“rc”: 0,

“start”: “2018-01-07 08:41:59.670709”,

“stderr”: “”,

“stderr_lines”: ,

“stdout”: “C:\Program Files\r\n”,

“stdout_lines”: [

“C:\Program Files”

]

}

META: ran handlers

META: ran handlers

As you can see I didn’t have to quote the chdir argument when defining it in YAML and the current directory changed to “C:\Program Files” in both the powershell and cmd instances.

You can find more info here https://docs.ansible.com/ansible/devel/windows_usage.html#running-commands, the argument rules is probably the most relevant.

Thanks

Jordan