Re: RFC: turn off word splitting for vars but keep for read
Greg Wooledge wrote: > Bob Proulx wrote: > > Aleksey Midenkov wrote: > > > rmcmd="$rmprog -f" > > > > > > Because it will fail for files with spaces. > > > > I am sure we disagree but I don't consider making rm program names > > have spaces to be reasonable. :-/ > > > > What would it be? "remove command"? I definitely would not consider > > an executable named with spaces that way to be reasonable. > > How about /mnt/c/Program Files/something/DEL.EXE? The directory might > contain spaces even if the command name itself does not. That would be using a full hard coded path. I think using full hard coded paths is bad for yet different reasons. Here in this context it might be argued that hard coding the path is part of a specific host's customization. But IMNHO it is always better to set PATH in that case. Because it is never just one command. It will almost always be several commands in an open ended list of possibilities. In which case you will need PATH set appropriately. Having a PATH with spaces in it won't cause a problem in this context. But in any case such host customizations are better to occur in a sourced configuration file and not in a production script itself. As a matter of style I very rarly would set options with the program name in a program name variable. (RSYNC_RSH comes to mind.) I would more typically set a companion $program_args variable instead. But then expect word splitting to occur in that args variable. So it is still the same issue just moved to a slightly different location. Bob
Re: RFC: turn off word splitting for vars but keep for read
On Sun, Nov 24, 2013 at 08:41:46PM -0700, Bob Proulx wrote: > Aleksey Midenkov wrote: > > rmcmd="$rmprog -f" > > > > Because it will fail for files with spaces. > > I am sure we disagree but I don't consider making rm program names > have spaces to be reasonable. :-/ > > What would it be? "remove command"? I definitely would not consider > an executable named with spaces that way to be reasonable. How about /mnt/c/Program Files/something/DEL.EXE? The directory might contain spaces even if the command name itself does not.
Re: RFC: turn off word splitting for vars but keep for read
Aleksey Midenkov wrote: > I would say, that this style generally is wrong: > > rmprog=${RMPROG-rm} > rmcmd="$rmprog -f" > > Because it will fail for files with spaces. I am sure we disagree but I don't consider making rm program names have spaces to be reasonable. :-/ What would it be? "remove command"? I definitely would not consider an executable named with spaces that way to be reasonable. Bob
Re: RFC: turn off word splitting for vars but keep for read
> ... > $ IFS="" > $ f() { echo $1; }; x="a b c"; f $x > a b c > > But, IFS influences `read`, which of course benefits from word > splitting. In light of that conflict, I propose two possible > solutions: > > 1: shopt -s unsplit_vars > > which will turn off word splitting for var expansion. > > or 2: new IFS2 var that will override IFS for `read` (i.e. `read` will > use IFS2 when IFS is unset). > Could also do: IFS=$'\n\t' echo "Checking..."; echo -n "$IFS"|hexdump The IFS on the read could be considered script documentation for the contents of the current file. Similar to awk's FS. while IFS=: read -re line; do : ; done < file Interesting read here, but pertains to splitting and filenames: http://www.dwheeler.com/essays/filenames-in-shell.html But could perhaps provide a supportive argument, maybe, for your suggestion option #1. http://mywiki.wooledge.org/Quotes is helpful. Peggy Russell
Re: RFC: turn off word splitting for vars but keep for read
On Fri, Nov 22, 2013 at 11:21 PM, Pierre Gaston wrote: > > > > On Fri, Nov 22, 2013 at 8:53 PM, Eric Blake wrote: >> >> On 11/22/2013 10:36 AM, Aleksey Midenkov wrote: >> >> > But nevertheless, I still find my proposal usable (since word >> > splitting for vars is unlikely to be usable in scripts). >> >> Scripts use word splitting on variables ALL the time. For example, I >> bet you have (multiple copies of) a script named install-sh somewhere on >> your system. It frequently uses word split variables, such as these >> setup lines: >> >> rmprog=${RMPROG-rm} >> ... >> rmcmd="$rmprog -f" >> >> for use in constructs like this: >> $doit $rmcmd -f "$dst" 2>/dev/null || >> >> Disabling word splitting for an interactive shell is one thing (and in >> fact, zsh has done that in their default mode), but for scripting, you >> would break LOTS of existing scripts if you changed the default behavior >> of word splitting. >> >> -- >> Eric Blake eblake redhat com+1-919-301-3266 >> Libvirt virtualization library http://libvirt.org >> > well, he proposes an option to turn on these behavior, not to change the > default behaviour. > I reckon something like shopt -s autoquote_expansions could be useful Exactly. I need this option only for my scripts, not for all scripts. shopt -s unsplit_vars will be shorter and more clear, IMHO. I would say, that this style generally is wrong: rmprog=${RMPROG-rm} rmcmd="$rmprog -f" Because it will fail for files with spaces. It is better (when don't worry about portability and backward compatibility like in autotools) to use array: rmcmd=("$rmprog" -f) and then: "${rmcmd[@])" But, these pesky double quotes we need to put everywhere because of word splitting.
Re: RFC: turn off word splitting for vars but keep for read
On Fri, Nov 22, 2013 at 8:53 PM, Eric Blake wrote: > On 11/22/2013 10:36 AM, Aleksey Midenkov wrote: > > > But nevertheless, I still find my proposal usable (since word > > splitting for vars is unlikely to be usable in scripts). > > Scripts use word splitting on variables ALL the time. For example, I > bet you have (multiple copies of) a script named install-sh somewhere on > your system. It frequently uses word split variables, such as these > setup lines: > > rmprog=${RMPROG-rm} > ... > rmcmd="$rmprog -f" > > for use in constructs like this: > $doit $rmcmd -f "$dst" 2>/dev/null || > > Disabling word splitting for an interactive shell is one thing (and in > fact, zsh has done that in their default mode), but for scripting, you > would break LOTS of existing scripts if you changed the default behavior > of word splitting. > > -- > Eric Blake eblake redhat com+1-919-301-3266 > Libvirt virtualization library http://libvirt.org > > well, he proposes an option to turn on these behavior, not to change the default behaviour. I reckon something like shopt -s autoquote_expansions could be useful
Re: RFC: turn off word splitting for vars but keep for read
> Yes, I know, I'd ever done alias for `read`: > > IFS="" > shopt -s expand_aliases > alias read='IFS=" " read' Why do you obfuscate your code with aliases? These just make debugging issues with your code harder. Remembering to quote variables and use a localized IFS for read is easier, than introducing an incompatible behaviour that will just help to make the confusion of shell scripting bigger. When giving support, it's easier to tell people: «Just double quote every parameter expansion when you're in doubt», than to list all the possible cases where they should and shouldn't. With your proposal, you're just adding a new variable to the mess... > But nevertheless, I still find my proposal usable (since word > splitting for vars is unlikely to be usable in scripts). Word splitting *IS* being used actively in lots of shell scripts that aim for POSIX compatibility (because it's the only way of pseudo-emulating arrays), and even it's used (wrongly) in bash scripts that do not aim to be compatible with the POSIX shell. So, if the user puts your shopt in ~/.bashrc and happens to run a script that relies on that... breakage. Also, lazyness is not a justification. Shell scripts are written once, but read and executed many times, so invest a little time into quoting properly, instead of relying on a modified IFS and set -f. Or use a language that doesn't have to be compatible with POSIX sh. Quoting isn't that hard once you get used to it ;) -- Eduardo Alan Bustamante López
Re: RFC: turn off word splitting for vars but keep for read
On 11/22/2013 10:36 AM, Aleksey Midenkov wrote: > But nevertheless, I still find my proposal usable (since word > splitting for vars is unlikely to be usable in scripts). Scripts use word splitting on variables ALL the time. For example, I bet you have (multiple copies of) a script named install-sh somewhere on your system. It frequently uses word split variables, such as these setup lines: rmprog=${RMPROG-rm} ... rmcmd="$rmprog -f" for use in constructs like this: $doit $rmcmd -f "$dst" 2>/dev/null || Disabling word splitting for an interactive shell is one thing (and in fact, zsh has done that in their default mode), but for scripting, you would break LOTS of existing scripts if you changed the default behavior of word splitting. -- Eric Blake eblake redhat com+1-919-301-3266 Libvirt virtualization library http://libvirt.org signature.asc Description: OpenPGP digital signature
Re: RFC: turn off word splitting for vars but keep for read
On Fri, Nov 22, 2013 at 7:07 PM, Pierre Gaston wrote: > > > > On Fri, Nov 22, 2013 at 8:00 AM, Aleksey Midenkov wrote: >> >> Since word splitting in vars is used not more frequently than never, >> protecting all vars in scripts with double quotes is quite unpleasant >> thing. Therefore, I want exactly this behavior always to be in my >> scripts: >> >> $ IFS="" >> $ f() { echo $1; }; x="a b c"; f $x >> a b c >> >> But, IFS influences `read`, which of course benefits from word >> splitting. In light of that conflict, I propose two possible >> solutions: >> >> 1: shopt -s unsplit_vars >> >> which will turn off word splitting for var expansion. >> >> or 2: new IFS2 var that will override IFS for `read` (i.e. `read` will >> use IFS2 when IFS is unset). > > > Your code is still not safe, you would need set -f to disable globing too. > > it's easy enough to set IFS locally for read, just set it in its environment > like > IFS=' ' read a b <<"hello world" > Yes, I know, I'd ever done alias for `read`: IFS="" shopt -s expand_aliases alias read='IFS=" " read' But nevertheless, I still find my proposal usable (since word splitting for vars is unlikely to be usable in scripts).
Re: RFC: turn off word splitting for vars but keep for read
On Fri, Nov 22, 2013 at 10:00:28AM +0400, Aleksey Midenkov wrote: > 1: shopt -s unsplit_vars > > which will turn off word splitting for var expansion. Basically, you want zsh.
Re: RFC: turn off word splitting for vars but keep for read
On Fri, Nov 22, 2013 at 8:00 AM, Aleksey Midenkov wrote: > Since word splitting in vars is used not more frequently than never, > protecting all vars in scripts with double quotes is quite unpleasant > thing. Therefore, I want exactly this behavior always to be in my > scripts: > > $ IFS="" > $ f() { echo $1; }; x="a b c"; f $x > a b c > > But, IFS influences `read`, which of course benefits from word > splitting. In light of that conflict, I propose two possible > solutions: > > 1: shopt -s unsplit_vars > > which will turn off word splitting for var expansion. > > or 2: new IFS2 var that will override IFS for `read` (i.e. `read` will > use IFS2 when IFS is unset). > Your code is still not safe, you would need set -f to disable globing too. it's easy enough to set IFS locally for read, just set it in its environment like IFS=' ' read a b <<"hello world"
RFC: turn off word splitting for vars but keep for read
Since word splitting in vars is used not more frequently than never, protecting all vars in scripts with double quotes is quite unpleasant thing. Therefore, I want exactly this behavior always to be in my scripts: $ IFS="" $ f() { echo $1; }; x="a b c"; f $x a b c But, IFS influences `read`, which of course benefits from word splitting. In light of that conflict, I propose two possible solutions: 1: shopt -s unsplit_vars which will turn off word splitting for var expansion. or 2: new IFS2 var that will override IFS for `read` (i.e. `read` will use IFS2 when IFS is unset).