command line - How to escape the arguments correctly when calling cygwin bash -c?

12
2014-01
  • kmp

    I am trying to call the scanimage command (from the SANE tool) from inside cygwin though I think that my problem is one of general escaping so maybe what I am calling doesn't matter. Anyway...

    The fly in the ointment is that I need to call said command from a windows command prompt (so calling bash.exe) and I cannot work out how to pass the arguments correctly. Here is an example:

    If I run up a cygwin terminal I can run this command and it works nicely:

     scanimage -d 'epson2:libusb:bus-0:\\.\libusb0-0001--0x04b8-0x012c' -y 20 --format tiff > out.tiff
    

    Great, but when I bring up a regular command prompt and put in this (the original command but inside the -c "" bit):

    "c:\cygwin\bin\bash.exe" --login -c "scanimage -d 'epson2:libusb:bus-0:\\.\libusb0-0001--0x04b8-0x012c' -y 20 --format tiff > out.tiff"
    

    I get back this error:

    scanimage: open of device epson2:libusb:bus-0:.\libusb0-0001--0x04b8-0x012c failed: Invalid argument

    This seems really odd to me, since how it is describing the argument in the error looks like it has got the correct value (if it hadn't passed it correctly I would expect it to be '' or something, but maybe that's just me).

    Incidentally, if I ditch the -d argument and do this

    "c:\cygwin\bin\bash.exe" --login -c "scanimage -y 20 --format tiff > out.tiff"
    

    all is good - except of course that if I connect another scanner I have a 50/50 chance of it scanning on the wrong one, so omitting the argument is not really an option.

    I thought of one way to do it: create a bsh file with the command in and then just launch that file from bash.exe ("c:\cygwin\bin\bash.exe" --login scan.bsh where scan.bsh contains the aforementioned command) but that seems, well, a bit icky.

    So my question is, therefore, how can I construct the command line for bash.exe such that, in this case, the device argument is properly passed and the scanner scans my stuff?

  • Answers
  • Nicole Hamilton

    You'll need to escape every \ in the command you're passing with an extra \.

    "c:\cygwin\bin\bash.exe" --login -c "scanimage -d 'epson2:libusb:bus-0:\\\\.\\libusb0-0001--0x04b8-0x012c' -y 20 --format tiff > out.tiff"
    

  • Related Question

    bash - (Cygwin 1.5.5-1 + CVS 1.11.21) vs. (cygwin-1.7.5 + CVS 1.11.22)
  • Android Eve

    Preparing a new machine for development, I upgraded Cygwin and the CVS client as described in the subject line: from (Cygwin 1.5.5-1 + CVS 1.11.21) to (cygwin-1.7.5 + CVS 1.11.22)

    All went well, but a 1-line convenience bash script I have been carrying around for years stopped working. It used to filter out all uninteresting lines from 'cvs status':

    cvs status | grep -F File | grep -v Up-to-date
    

    In the new version, it seemed as if "grep -v" simply stopped working (i.e. wasn't filtering OUT anything). So I tried:

    cvs status 2>&1 | grep -F File | grep -v Up-to-date
    

    But that didn't change the behavior. The output was still as if "grep -v" were never called. So, I tried:

    cvs status 2>&1 | grep -F File 2>&1 | grep -v Up-to-date
    

    And that solved the problem! The script now behaves identically in (Cygwin 1.5.5-1 + CVS 1.11.21) and (cygwin-1.7.5 + CVS 1.11.22).

    My question now is why?

    What happened to Cygwin's grep that it now requires redirection from stderr to stdout?

    Please note that I intentionally emphasized the word script, because the original command (the first one quoted above) still works identically in both old and new environments, if typed from the command line (i.e. not inside a #!/bin/bash script).

    Any idea why this is?


  • Related Answers
  • garyjohn

    I don't know for sure in this case, but a common cause of scripts failing to work with newer versions of Cygwin's bash is DOS (CR-LF) line endings. Perhaps your last change to that script also changed the line ending. Make sure your scripts use only Unix (LF) line endings. Otherwise, grep will see its pattern argument as "Up-to-date^M".

  • Android Eve

    It's time to accept an answer. The only reasonable explanation so far is that something has changed in they way Cygwin's grep splits output to stderr and stdout. If a better or more authoritative answer comes along, I will consider accepting it.