opening file vs. opening pipeline on NT. 
Author Message
 opening file vs. opening pipeline on NT.

I have found an inconsistency in Tcl7.6 under MS Windows NT 3.51, as
demonstrated by the following code segment.  The code segment shows
that backslashes in a file name are treated differently depending upon
whether the file is being opened as a regular file or as a command
pipeline.  When opened as a regular file name, the backslashes are
preserved.  When opened as a command pipe line, blackslash substitution
appears to be (re)occuring, thereby distorting the original file name.
(Incidentally, 'exec'ing $file works okay.)

===
set file "c:\\users\\donald\\hello.exe"
puts "Opening file ..."
if [catch {set fp [open $file r]} msg] {     ;# This is okay.
        puts "Cannot open file: $msg"

Quote:
} else {
        close $fp
}

puts "Opening command pipeline ..."
if [catch {set fp [open |$file r]} msg] {    ;# This is not okay.
        puts "Cannot open pipe: $msg"
Quote:
} else {
        close $fp
}

===

The first open succeeds, but the second one generates the message:
    "couldn't execute "c:usersdonaldhello.exe": no such file or directory"

There seem to be two workarounds for this problem.  Either use forward
slashes instead of backslashes as the directory separator in the file
name, or regsub all the backslashes with double backslashes before
opening the file as a command pipeline.  The script will then work as
expected.

--
Donald Craig



Thu, 29 Apr 1999 03:00:00 GMT  
 opening file vs. opening pipeline on NT.


Quote:

>I have found an inconsistency in Tcl7.6 under MS Windows NT 3.51, as
>demonstrated by the following code segment.  The code segment shows
>that backslashes in a file name are treated differently depending upon
>whether the file is being opened as a regular file or as a command
>pipeline.  When opened as a regular file name, the backslashes are
>preserved.  When opened as a command pipe line, blackslash substitution
>appears to be (re)occuring, thereby distorting the original file name.

>set file "c:\\users\\donald\\hello.exe"
>puts "Opening file ..."
>if [catch {set fp [open $file r]} msg] {     ;# This is okay.
>        puts "Cannot open file: $msg"
>} else {
>        close $fp
>}
>puts "Opening command pipeline ..."
>if [catch {set fp [open |$file r]} msg] {    ;# This is not okay.
>        puts "Cannot open pipe: $msg"
>} else {
>        close $fp
>}
>===

>The first open succeeds, but the second one generates the message:
>    "couldn't execute "c:usersdonaldhello.exe": no such file or directory"

----------------------------------------------------------
Quick answer: The strictly proper way to open a command pipeline to a
program with arguments is:

open |[list myprogram myarg1 myarg2]

even if there aren't any backslashes in myprogram or myargs.  Even if there
are no arguments, the proper way is still:

open |[list myprogram]

-----------------------------------------------------------
Longer explanation:

The problem lies in the dual behavior of the "open" command.

If the first character of the first argument to "open" is a "|", then the
remaining characters in the first argument must make up a proper Tcl list
that describes the program and any arguments to that program.  

The above "double-substitution" problem seems to arise only because open
treats its first argument as a list, and it seems so easy to assume that a
string is equivalent to a list of 1 element.  
However, given the following:

set f "c:\\name"

The variable f is the string whose bytes are:   c  :  \  n  a  m  e
The variable f is also a 1 element list whose first element is the
string whose bytes are   c  :  \n  a  m  e
                         ^  ^  ^^  ^  ^  ^
You can try this yourself:
% lindex $f 0
c:
ame

Incidentally, to get the 1 element list whose first element is the string
whose bytes are  c  :  \  n  a  m  e

% list $f
{c:\name}

The first-level backslashes were substituted out when assigning the
value to your variable.  The argument to open was treated as a list and its
elements (all one of them) were extracted out.  Tcl graciously forgave
your mistake of providing the unknown backslash escape sequences \u, \d,
and \h and treated them as the literal characters u, d, and h.

This problem doesn't happen with exec because exec doesn't take a list.
It takes separate arguments that specify the name of the external program and
any arguments to that program:

exec myprogram myarg1 myarg2

Because open takes a list, you must pass it a list.  That's the answer.
I thought Tcl was broken when I first read the problem, but Tcl is just being
consistent.

If this still doesn't quite make sense, try playing with lists with more than
one element, which makes it clearer why this is happening.  For example:

% set f "puts hi\\nthere"
puts hi\nthere
% lindex $f 0
puts
% lindex $f 1
hi
there
% eval $f
hi
there

vs.

% set f "puts hi\nthere"
puts hi
there
% eval $f
hi
invalid command name "there"



Sat, 01 May 1999 03:00:00 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. Opening file vs. opening pipeline on NT.

2. LV5 VISA Open vs LV6 VISA Open

3. open vs. open

4. File Open, or not Open, question

5. OPEN(VIEW) without OPEN(FILE)

6. Opening a file already open

7. opening existing files with OPEN()

8. opening a file opens it in Notepad

9. opening 'file open' dialog from console

10. multiple use of with-open-file, or with-open-stream

11. pipeline with [open r+] problem

12. Need to close and re-open a process pipeline

 

 
Powered by phpBB® Forum Software