bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

The IFS variable - a confusing issue.


From: cga
Subject: The IFS variable - a confusing issue.
Date: Thu, 07 Oct 2004 13:26:44 -0400
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624

I ran into this code snippet in "Learning the Bash Shell" - Cameron Newham & Bill Rosenblatt - O'Reilly (page 248):

     1 #!/bin/bash2
     2 IFS=:
     3 for d in $PATH; do
     4         echo checking $d:
     5         cd $d
     6         scripts=$(file * | grep 'shell script' | cut -d: -f1)
     7         for f in $script do
     8                 grep '\^' $f /dev/null
     9         done
    10 done

This did not work in my setup - in my mind because while the list used for the external "for" loop (line 1/10) uses ":" as a separator (PATH="dir1:dir2:dir3"..) the pipeline on line 6 generates a space-delimited list of files - i.e. "file1 file2 file3 ... file99" but unfortunately, since the IFS variable now contains only ":" this leads the "for" command on line 7 to believe that it is dealing with a one-item list ("file1 file2.. etc") and the ensuing "grep" attempts to search a file named "file1 file2 .. file99" - in my case causing it to fail with a "file name too long" message.

I replaced line 2 by the following:

      2 IFS=${IFS}:

.. and apparently got the above code to work.

But just to make sure that the modified assignment did what I intended.. I had also added an "echo $IFS" immediately after and this did not give me the expected result. The IFS variable echoed as ":" - not " :" as I had anticipated.. or " :".. or even " :" - just ":".

I proceeded to try & check the initial contents of the IFS variable interactively like so:

$ bash
$ marker=zob
$ echo ${IFS)${marker}
zob
$ This again was not quite what I expected. Since the default contents of IFS are "space,tab,newline" I thought that the contents of "marker" would be pushed one line down:

$ echo ${IFS)${marker}

zob
$ I looked for something in bash that would display unprintable variable contents in one form or another - the ascii code or an escaped sequence equivalent, but I did not find what I was looking for, so I tried the following:

$ bash
$ declare -p IFS
declare -- IFS="        \
"
$ ifsave=${IFS}
$ IFS=${IFS}:
$ declare -p IFS
declare -- IFS="        \
"
$ IFS=${ifsave}
$ declare -p IFS
declare -- IFS="        \
"
This would tend to prove that everything does work as I had initially assumed when I attempted to correct the sample code from the O'Reilly book. But I am still a bit unsure about my conclusions. As far as I know my "fix" might work for entirely different reasons..

Could anyone confirm that I got to the bottom of this.. or explain what I missed or misunderstood?

In particular:

1. The bash man page describes IFS as a special variable. What does the "special" imply?

2. Is it good bash programming practice to modify, save, and restore the contents of the IFS variable? It looks like a powerful, elegant technique but likely to be a source of later headaches if used incorrectly..

3. The bash man page does not mention IFS explicitly when describing the "for" construct. Am I correct in assuming that "for" uses the contents of the IFS variable to parse a character string into words?

4. I am still using bash 2.05 but I see in the bash 3.0 Reference Manual that "word splitting" is now done differently, thus closing a "longstanding security hole". Where could I find more info concerning this, in particular regarding whether it affects bash 2.05 and what exactly was this vulnerability? I apologize for the verbose post but surely part of the blame must rest on the authors of the O'Reilly book. I'm sure an experienced bash programmer would have spotted the error immediately but a newcomer to the area implicitly trusts the printed word and looks closer to home for an explanation. Aren't examples supposed to clarify the subject matter rather than make it more confusing?










reply via email to

[Prev in Thread] Current Thread [Next in Thread]