public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* Re: Problem passing file names with embedded space to Windows executable via bash function
@ 2015-06-26 21:28 ncokwqc02
  0 siblings, 0 replies; 4+ messages in thread
From: ncokwqc02 @ 2015-06-26 21:28 UTC (permalink / raw)
  To: cygwin

[ This is meant to be a reply to the response post by Ernie Rael, which I managed to lose so there is no referencing. ]

On 6/26/2015 12:50 PM, Ernie Rael wrote:

>I use something similar to this, perhaps it would meet your needs. You may want to use >different option to cygpath.
>
>   #!/usr/bin/bash
>
>   targs() {
>        if (($# == 0)); then
            _         _
>            args=()
>        else
>            IFS=$'\n'
                 _
>            args=($(cygpath -m -- "$@"))
                  ___           __     __
>            IFS=$' \t\n'
                 _
>        fi
>
>        for i in "${args[@]}"; do echo "'$i'"; done
>
>        some_command "${args[@]}"
                             ___
>   }
>
>
>-ernie

I modified Ernie's solution for my purposes and it works beautifully. Thanks so much.

The key point seems to be the temporary redefinition of IFS.

However, Ernie's solution also incorporates other features / syntactical elements of bash that I would never have thought to use and I'm interested to know if they are necessary and what they do. They are underlined in the message above. 

Basically,
1. Why the '(( .... ))' syntax with 'if'? Same as '[ .... ]'?
2. Why precede the white space characters with '$'?
3. Why enclose the 'cygpath' command by '($( ... ))'?
4. What does '--' do for 'cygpath'?
5. Why 'args[@]' rather than just 'args'?

Anyway, thanks for the simple solution to my problem. If I learn some more about obscure bash syntax that will be a bonus.

jjo


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Problem passing file names with embedded space to Windows executable via bash function
@ 2015-06-26 22:31 Ernie Rael
  0 siblings, 0 replies; 4+ messages in thread
From: Ernie Rael @ 2015-06-26 22:31 UTC (permalink / raw)
  To: cygwin

On 6/26/2015 2:27 PM, ncokwqc02@sneakemail.com wrote:
> [ This is meant to be a reply to the response post by Ernie Rael, which I managed to lose so there is no referencing. ]
>
> On 6/26/2015 12:50 PM, Ernie Rael wrote:
>
>> I use something similar to this, perhaps it would meet your needs. You may want to use >different option to cygpath.
>>
>>    #!/usr/bin/bash
>>
>>    targs() {
>>         if (($# == 0)); then
>              _         _
>>             args=()
>>         else
>>             IFS=$'\n'
>                   _
>>             args=($(cygpath -m -- "$@"))
>                    ___           __     __
>>             IFS=$' \t\n'
>                   _
>>         fi
>>
>>         for i in "${args[@]}"; do echo "'$i'"; done
>>
>>         some_command "${args[@]}"
>                               ___
>>    }
>>
>>
>> -ernie
> I modified Ernie's solution for my purposes and it works beautifully. Thanks so much.
>
> The key point seems to be the temporary redefinition of IFS.
>
> However, Ernie's solution also incorporates other features / syntactical elements of bash that I would never have thought to use and I'm interested to know if they are necessary and what they do. They are underlined in the message above.

IMHO you are best served by looking up the stuff in the bash 
documentation; that's a good way to learn new stuff when exploring 
example code. Do "man bash", search and enjoy; you can search with REs. 
But here's some hints.

To handle a list of files, bash arrays are convenient.

> Basically,
> 1. Why the '(( .... ))' syntax with 'if'? Same as '[ .... ]'?
arithmetic - search for ((: /\(\(
> 2. Why precede the white space characters with '$'?
that's $'stuff' search: /\$'
> 3. Why enclose the 'cygpath' command by '($( ... ))'?
that's two things:
$() - search: /\$\(          (but skip past the "$((")
and xxx=() search: /=\(
The "$()" construct replaces the ancient `` syntax, xxx=() is for arrays
> 4. What does '--' do for 'cygpath'?
The '--' is not cygpath specific. Try man getopt. Note the difference 
between entering
"cygpath -- -m" and "cygpath -m"
> 5. Why 'args[@]' rather than just 'args'?
Check this out under "Arrays" in the docs. just "$args" is the first 
element of the array.
Definitely want @ not *
>
> Anyway, thanks for the simple solution to my problem. If I learn some more about obscure bash syntax that will be a bonus.
>
> jjo
>
>
> --
> Problem reports:       http://cygwin.com/problems.html
> FAQ:                   http://cygwin.com/faq/
> Documentation:         http://cygwin.com/docs.html
> Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
>
>
>


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Problem passing file names with embedded space to Windows executable via bash function
  2015-06-26 19:06 JJ Ottusch
@ 2015-06-26 19:51 ` Ernie Rael
  0 siblings, 0 replies; 4+ messages in thread
From: Ernie Rael @ 2015-06-26 19:51 UTC (permalink / raw)
  To: cygwin

On 6/26/2015 12:06 PM, JJ Ottusch wrote:
> I am trying to define a function in my '.bash_profile' that takes a file or
> list of files as an argument and passes the list to a Windows executable
> after converting all the filenames to full path filenames with 'cygpath'.

I use something similar to this, perhaps it would meet your needs. You 
may want to use different option to cygpath.

    #!/usr/bin/bash

    targs() {
         if (($# == 0)); then
             args=()
         else
             IFS=$'\n'
             args=($(cygpath -m -- "$@"))
             IFS=$' \t\n'
         fi

         for i in "${args[@]}"; do echo "'$i'"; done

         some_command "${args[@]}"
    }


-ernie

>
> The whole point of the function is to use 'cygpath' to put the filenames in a
> Windows compatible format for me so I don't have to do it every time I call
> the Windows executable from a CYGWIN term.
>
> My function works fine except in cases where any part of the path or filename
> contains a space. In that case the list of arguments the Windows executable
> sees is incorrectly broken apart by the embedded spaces. I can verify this by
> looking at argc.
>
>
> Here are some examples with comments. All commands run from
> '/cygdrive/c/Temp/Part1\ Part2/' in a CYGWIN RXVT term.
>
>
> Let the windows executable be named 'oglv64' and start with the usual
> 	int main(int argc, char** argv)
> Let there be two files it can take as arguments named 'file1' and 'file2' in
> the directory '/cygdrive/c/Temp/Part1 Part2', where 'Part1 Part2' is a
> subdirectory name with an embedded space. Let the defined function be named
> 'foo'.
>
>
> 1. Show the files
>
> $ dir /cygdrive/c/Temp/Part1\ Part2/
> file1*  file2*
>
> 2. Test the function with 'echo' instead of 'oglv64'. 'cygpath' works
> correctly on each file, but there is a bare space between 'Part1' and 'Part2'
> which can be expected to cause problems with 'oglv64'.
>
> $ foo() { echo `cygpath -am "$@"` ; }; foo file*
> C:/Temp/Part1 Part2/file1 C:/Temp/Part1 Part2/file2
>
> 3. So, escape the space. Looks good.
>
> $ foo() { echo `cygpath -am "$@" | sed 's/ /\\\ /'` ; }; foo file*
> C:/Temp/Part1\ Part2/file1 C:/Temp/Part1\ Part2/file2
>
> 4. Although I can't show it, the Window executable works exactly as desired
> when given the above line as its input. argc=3 and 'oglv64' operates on the
> two files as desired.
>
> $ oglv64 C:/Temp/Part1\ Part2/file1 C:/Temp/Part1\ Part2/file2
>
> 5. Now try this inside the function definition. As shown below, this didn't
> work. argc=5 instead of 3.
>
> $ foo() { oglv64 `cygpath -am "$@" | sed 's/ /\\\ /'` ; }; foo file*
> Can't load C:/Temp/Part1\.
> Can't load Part2/file1.
> Can't load C:/Temp/Part1\.
> Can't load Part2/file2.
>
> 6. Put the full argument in quotes and try again. The 'echo' result is
> correct, but given on two separate lines. However, the Windows executable
> sees argc=2 and thinks it's all one long filename. Wrong, as expected.
>
> $ foo() { echo "`cygpath -am \"$@\" | sed 's/ /\\\ /'`" ; }; foo file*
> C:/Temp/Part1\ Part2/file1
> C:/Temp/Part1\ Part2/file2
>
> $ foo() { oglv64 "`cygpath -am \"$@\" | sed 's/ /\\\ /'`" ; }; foo file*
> Can't load C:/Temp/Part1\ Part2/file1
> C:/Temp/Part1\ Part2/file2.
>
> 7. Drop the escaped space and try forcing quotes at the end of each 'cygpath'
> result. Looks fine with 'echo', but the Windows executable still sees argc=5
> rather than argc=3.
>
> $ foo() { echo `cygpath -am "$@" | sed 's/^/\"/;s/$/\"/'` ; }; foo file*
> "C:/Temp/Part1 Part2/file1" "C:/Temp/Part1 Part2/file2"
>
> $ foo() { oglv64 `cygpath -am "$@" | sed 's/^/\"/;s/$/\"/'` ; }; foo file*
> Can't load "C:/Temp/Part1.
> Can't load Part2/file1".
> Can't load "C:/Temp/Part1.
> Can't load Part2/file2".
>
> 8 On the other hand, using the output from 'echo' as a direct argument to
> 'oglv64' works fine.
>
> $ oglv64 "C:/Temp/Part1 Part2/file1" "C:/Temp/Part1 Part2/file2"
>
>
> No success so far. I am looking to find a simple solution to this problem
> (other than eliminating spaces from all file/directory names). It would have
> multiple applications.
>
> jjo
>
>
> --
> Problem reports:       http://cygwin.com/problems.html
> FAQ:                   http://cygwin.com/faq/
> Documentation:         http://cygwin.com/docs.html
> Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
>
>
>


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Problem passing file names with embedded space to Windows executable via bash function
@ 2015-06-26 19:06 JJ Ottusch
  2015-06-26 19:51 ` Ernie Rael
  0 siblings, 1 reply; 4+ messages in thread
From: JJ Ottusch @ 2015-06-26 19:06 UTC (permalink / raw)
  To: cygwin

I am trying to define a function in my '.bash_profile' that takes a file or 
list of files as an argument and passes the list to a Windows executable 
after converting all the filenames to full path filenames with 'cygpath'. 

The whole point of the function is to use 'cygpath' to put the filenames in a 
Windows compatible format for me so I don't have to do it every time I call 
the Windows executable from a CYGWIN term.

My function works fine except in cases where any part of the path or filename 
contains a space. In that case the list of arguments the Windows executable 
sees is incorrectly broken apart by the embedded spaces. I can verify this by 
looking at argc.


Here are some examples with comments. All commands run from 
'/cygdrive/c/Temp/Part1\ Part2/' in a CYGWIN RXVT term.


Let the windows executable be named 'oglv64' and start with the usual
	int main(int argc, char** argv)
Let there be two files it can take as arguments named 'file1' and 'file2' in 
the directory '/cygdrive/c/Temp/Part1 Part2', where 'Part1 Part2' is a 
subdirectory name with an embedded space. Let the defined function be named 
'foo'.


1. Show the files

$ dir /cygdrive/c/Temp/Part1\ Part2/
file1*  file2*

2. Test the function with 'echo' instead of 'oglv64'. 'cygpath' works 
correctly on each file, but there is a bare space between 'Part1' and 'Part2' 
which can be expected to cause problems with 'oglv64'.

$ foo() { echo `cygpath -am "$@"` ; }; foo file*
C:/Temp/Part1 Part2/file1 C:/Temp/Part1 Part2/file2

3. So, escape the space. Looks good.

$ foo() { echo `cygpath -am "$@" | sed 's/ /\\\ /'` ; }; foo file*
C:/Temp/Part1\ Part2/file1 C:/Temp/Part1\ Part2/file2

4. Although I can't show it, the Window executable works exactly as desired 
when given the above line as its input. argc=3 and 'oglv64' operates on the 
two files as desired.

$ oglv64 C:/Temp/Part1\ Part2/file1 C:/Temp/Part1\ Part2/file2

5. Now try this inside the function definition. As shown below, this didn't 
work. argc=5 instead of 3.

$ foo() { oglv64 `cygpath -am "$@" | sed 's/ /\\\ /'` ; }; foo file*
Can't load C:/Temp/Part1\.
Can't load Part2/file1.
Can't load C:/Temp/Part1\.
Can't load Part2/file2.

6. Put the full argument in quotes and try again. The 'echo' result is 
correct, but given on two separate lines. However, the Windows executable 
sees argc=2 and thinks it's all one long filename. Wrong, as expected.

$ foo() { echo "`cygpath -am \"$@\" | sed 's/ /\\\ /'`" ; }; foo file*
C:/Temp/Part1\ Part2/file1
C:/Temp/Part1\ Part2/file2

$ foo() { oglv64 "`cygpath -am \"$@\" | sed 's/ /\\\ /'`" ; }; foo file*
Can't load C:/Temp/Part1\ Part2/file1
C:/Temp/Part1\ Part2/file2.

7. Drop the escaped space and try forcing quotes at the end of each 'cygpath' 
result. Looks fine with 'echo', but the Windows executable still sees argc=5 
rather than argc=3.

$ foo() { echo `cygpath -am "$@" | sed 's/^/\"/;s/$/\"/'` ; }; foo file*
"C:/Temp/Part1 Part2/file1" "C:/Temp/Part1 Part2/file2"

$ foo() { oglv64 `cygpath -am "$@" | sed 's/^/\"/;s/$/\"/'` ; }; foo file*
Can't load "C:/Temp/Part1.
Can't load Part2/file1".
Can't load "C:/Temp/Part1.
Can't load Part2/file2".

8 On the other hand, using the output from 'echo' as a direct argument to 
'oglv64' works fine.

$ oglv64 "C:/Temp/Part1 Part2/file1" "C:/Temp/Part1 Part2/file2"


No success so far. I am looking to find a simple solution to this problem 
(other than eliminating spaces from all file/directory names). It would have 
multiple applications.

jjo


--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-06-26 22:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-26 21:28 Problem passing file names with embedded space to Windows executable via bash function ncokwqc02
  -- strict thread matches above, loose matches on Subject: below --
2015-06-26 22:31 Ernie Rael
2015-06-26 19:06 JJ Ottusch
2015-06-26 19:51 ` Ernie Rael

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).