Bug#515234: bash fails to process files separately with for name in *
The traces you provide show that what's happening is actually that the *, being expanded in a directory with no files, expands to the literal '*', which is somewhat awkward with which to deal but which is mandated by POSIX for /bin/sh: From http://www.opengroup.org/onlinepubs/95399/utilities/xcu_chap02.html#tag_02_13, retrieved on 2009-05-10: | If the pattern contains an invalid bracket expression or does not | match any existing filenames or pathnames, the pattern string shall | be left unchanged. So why are all these other filenames appearing in the trace? Simple: because you don't use the correct double-quoting around your use of $f, and so [ -w /sys/module/speakup/parameters/$f ] gets expanded to [ -w /sys/module/speakup/parameters/* ] and then the * gets expanded in that context. Note that this probably means that the script is already broken in the case of filenames in the starting directory that contain whitespace or pattern-matching metacharacters. --- Drake Wilson -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of unsubscribe. Trouble? Contact listmas...@lists.debian.org
Bug#515234: bash fails to process files separately with for name in *
Package: bash Version: 3.2-4 Severity: normal The man page for bash states: for name [ in word ] ; do list ; done The list of words following in is expanded, generating a list of items. The variable name is set to each element of this list in turn, and list is executed each time. ... This has been the expected behavior of for name in word since the introduction of the Bourne shell, 30 years ago. In the case of for name in *, bash executes the loop only once with name set to the entire list of all the files in the current directory. This means that a significant number of scripts do not work as they should. I have generated the following test cases from a script called speakupconf that is distributed with the speakup-doc package. I am sure that I have seen this problem with scripts that I have written, as well. The first case is using the script as distributed. I created the second and third cases by using alternate formats for the for statement. The forth case uses ls to generate the file list, and is the only one that works. Case 1: asterisk adjacent to semicolon #!/bin/sh set -x # script to load/save all the vars in speakup # speakupconf save or speakupconf load # if root saves in /etc/speakup/synth else in $HOME/.speakup/synth if [ $UID -eq 0 ]; then SAVEDIR=/etc/speakup else SAVEDIR=$HOME/.speakup fi if [ ! -d /sys/module/speakup/parameters ]; then echo no directory /sys/module/speakup/parameters exit 0 fi SYNTH=`cat /sys/module/speakup/parameters/synth` case $1 in *save) if [ ! -d $SAVEDIR ] ; then echo creating $SAVEDIR mkdir $SAVEDIR fi if [ ! -d $SAVEDIR/$SYNTH ] ; then echo creating $SAVEDIR/$SYNTH mkdir $SAVEDIR/$SYNTH fi cd /sys/module/speakup/parameters SAVELIST=`find . -perm -6 |sed 's/..//' |fgrep -v synth` for f in $SAVELIST; do cp $f $SAVEDIR/$SYNTH/$f done ;; *load) if [ ! -d $SAVEDIR ] ; then echo no directory $SAVEDIR exit 1 fi if [ ! -d $SAVEDIR/$SYNTH ] ; then echo no directory $SAVEDIR/$SYNTH exit 1 fi cd $SAVEDIR/$SYNTH for f in *; do if [ -w /sys/module/speakup/parameters/$f ]; then cat $f /sys/module/speakup/parameters/$f fi done ;; *) echo usage: speakupconf load/save exit 1 ;; esac Results 1: + '[' 0 -eq 0 ']' + SAVEDIR=/etc/speakup + '[' '!' -d /sys/module/speakup/parameters ']' ++ cat /sys/module/speakup/parameters/synth + SYNTH=ltlk + case $1 in + '[' '!' -d /etc/speakup ']' + '[' '!' -d /etc/speakup/ltlk ']' + cd /etc/speakup/ltlk + for f in '*' + '[' -w /sys/module/speakup/parameters/attrib_bleep /sys/module/speakup/parameters/bell_pos /sys/module/speakup/parameters/bleeps /sys/module/speakup/parameters/bleep_time /sys/module/speakup/parameters/caps_start /sys/module/speakup/parameters/caps_stop /sys/module/speakup/parameters/characters /sys/module/speakup/parameters/chartab /sys/module/speakup/parameters/cursor_time /sys/module/speakup/parameters/delay_time /sys/module/speakup/parameters/delimiters /sys/module/speakup/parameters/ex_num /sys/module/speakup/parameters/freq /sys/module/speakup/parameters/full_time /sys/module/speakup/parameters/jiffy_delta /sys/module/speakup/parameters/key_echo /sys/module/speakup/parameters/keymap /sys/module/speakup/parameters/lang /sys/module/speakup/parameters/no_interrupt /sys/module/speakup/parameters/pitch /sys/module/speakup/parameters/punc_all /sys/module/speakup/parameters/punc_level /sys/module/speakup/parameters/punc_most /sys/module/speakup/parameters/punc_some /sys/module/speakup/parameters/punct /sys/module/speakup/parameters/quiet /sys/module/speakup/parameters/rate /sys/module/speakup/parameters/reading_punc /sys/module/speakup/parameters/repeats /sys/module/speakup/parameters/say_control /sys/module/speakup/parameters/say_word_ctl /sys/module/speakup/parameters/silent /sys/module/speakup/parameters/spell_delay /sys/module/speakup/parameters/synth /sys/module/speakup/parameters/synth_direct /sys/module/speakup/parameters/tone /sys/module/speakup/parameters/trigger_time /sys/module/speakup/parameters/version /sys/module/speakup/parameters/voice /sys/module/speakup/parameters/vol ']' /usr/local/bin/speakupconf: line 43: [: too many arguments Case 2: space between asterisk and semicolon #!/bin/sh set -x # script to load/save all the vars in speakup # speakupconf save or speakupconf load # if root saves in /etc/speakup/synth else in $HOME/.speakup/synth if [ $UID -eq 0 ]; then SAVEDIR=/etc/speakup else SAVEDIR=$HOME/.speakup fi if [ ! -d /sys/module/speakup/parameters ]; then echo no directory /sys/module/speakup/parameters exit 0 fi SYNTH=`cat /sys/module/speakup/parameters/synth` case $1 in *save) if [ ! -d $SAVEDIR ] ; then echo creating $SAVEDIR mkdir $SAVEDIR fi if [ ! -d $SAVEDIR/$SYNTH ] ; then echo creating $SAVEDIR/$SYNTH mkdir $SAVEDIR/$SYNTH fi cd /sys/module/speakup/parameters