[opensuse] bash - why doesn't the tldp bash beginners guide for loop example work?
Listmates, I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation. I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html The example give is: [carol@octarine ~/html] cat html2php.sh #!/bin/bash # specific conversion script for my html files to php LIST="$(ls *.html)" for i in "$LIST"; do NEWNAME=$(ls "$i" | sed -e 's/html/php/') cat beginfile > "$NEWNAME" cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME" cat endfile >> "$NEWNAME" done So I created the following: #!/bin/bash LIST="$(ls *.zip)" for i in "$LIST"; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0 It didn't work?? The echo statement showed that $i was receiving the entire $LIST and the loop was only executing once instead of once for each entry in $LIST. Fiddling with it, I got it to work by removing the quotes "" from $LIST in the loop definition like this: #!/bin/bash LIST="$(ls *.zip)" for i in $LIST; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0 I understand enough to realize the quotes affect bash expansion, but I am curious as to whether the tldp example is in error. What says the brain trust? -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Wed, 13 Feb 2008, David C. Rankin wrote:-
Listmates,
I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation.
I'll give you three guesses which one...
I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html
The example give is:
[carol@octarine ~/html] cat html2php.sh #!/bin/bash # specific conversion script for my html files to php LIST="$(ls *.html)" for i in "$LIST"; do NEWNAME=$(ls "$i" | sed -e 's/html/php/') cat beginfile > "$NEWNAME" cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME" cat endfile >> "$NEWNAME" done
Oh, oh. There's an error in that. As you guessed, the quotes around "$LIST" shouldn't be there. Using some HTML files in one of my directories as an example: davjam@adder:~/public_html> ls *.htm index.htm pics1.htm spam3days.htm spams7day.htm spamstats.htm pic.htm rsync.example.htm spams3day.htm spams_per_day.htm you.htm That shows the files, just for reference. davjam@adder:~/public_html> LIST="$(ls *.htm)" That's the first line in that script. davjam@adder:~/public_html> echo "${LIST}" index.htm pic.htm pics1.htm rsync.example.htm spam3days.htm spams3day.htm spams7day.htm spams_per_day.htm spamstats.htm you.htm And there was the contents of $LIST. davjam@adder:~/public_html> for i in "${LIST}"; do echo "\"${i}\""; done "index.htm pic.htm pics1.htm rsync.example.htm spam3days.htm spams3day.htm spams7day.htm spams_per_day.htm spamstats.htm you.htm" Now, here I've passed "$LIST" to the for loop and the body just prints the contents of $i and adds quotes around it so you can see just what is passed as $i. As you can see, there is a double-quote at the beginning of the first line, and the closing quotes at the end of the last line. This says that everything in between those quotes was assigned to $i in one go. As you correctly guessed, the quotes around $LIST shouldn't have been there, and removing them gets this output instead: davjam@adder:~/public_html> for i in ${LIST}; do echo "\"${i}\""; done "index.htm" "pic.htm" "pics1.htm" "rsync.example.htm" "spam3days.htm" "spams3day.htm" "spams7day.htm" "spams_per_day.htm" "spamstats.htm" "you.htm" <Snip>
I understand enough to realize the quotes affect bash expansion, but I am curious as to whether the tldp example is in error. What says the brain trust?
Yes, there's an error in the tldp example. Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Wednesday 13 February 2008 20:41, David C. Rankin wrote:
Listmates,
I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation.
I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html
It sounds like someone needs to submit some feedback to the author or maintainer of that document.
The example give is:
...
So I created the following:
#!/bin/bash LIST="$(ls *.zip)" for i in "$LIST"; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0
It didn't work?? The echo statement showed that $i was receiving the entire $LIST and the loop was only executing once instead of once for each entry in $LIST. Fiddling with it, I got it to work by removing the quotes "" from $LIST in the loop definition like this:
#!/bin/bash LIST="$(ls *.zip)" for i in $LIST; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0
I understand enough to realize the quotes affect bash expansion, but I am curious as to whether the tldp example is in error. What says the brain trust?
That's what quotes do. They create a single string. The ones where LIST is defined are required because a shell variable (that is not an array) can have only a single value and ordinary parsing would break the output of ls at each occurrence of a (run of) whitespace characters. The one in the "for" loop, where any number of words is allowed, causes there to be only one, holding the entire output from the "ls" invocation. I personally like to use array variables in BASH scripting. They're very hand because they can be spread across multiple lines _without_ using backslashes and by putting a single value on each line, you can easily comment out certain values by commenting the line that contains them within the array initialization. Also, you can get item-by-item quoting when expanding an array. Consider this array: numbers=( 0 I two 3 ) for number in "${numbers[@]}"; do echo $number done Echo will be invoked four times in this loop. This variant get all the array elements expanded in single quoted string: for number in "${numbers[*]}"; do echo $number done In this case, echo will be invoked only once. When you combine arrays with command substitution (the $( command ) notation) and pipes, you can get pretty fancy about generating value lists to operate on.
-- David C. Rankin, J.D., P.E.
Randall Schulz -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thu, 14 Feb 2008, Randall R Schulz wrote:-
That's what quotes do. They create a single string. The ones where LIST is defined are required because a shell variable (that is not an array) can have only a single value and ordinary parsing would break the output of ls at each occurrence of a (run of) whitespace characters.
No it doesn't. Try this on a command line: LIST=$(ls -1) ; echo "\"${LIST}\"" This will perform an ls in the PWD, and assign the results to LIST. The echo statement then displays the contents of $LIST and wraps it in quotes so you can see the start and end of the variables contents. You should see something like this: davjam@adder:~/temp> ls 200802052337 200802061302 count.all count.txt 200802052337.sorted 200802061302.sorted count.sorted extract.sh davjam@adder:~/temp> LIST=$(ls -1) ; echo "\"${LIST}\"" "200802052337 200802052337.sorted 200802061302 200802061302.sorted count.all count.sorted count.txt extract.sh"
The one in the "for" loop, where any number of words is allowed, causes there to be only one, holding the entire output from the "ls" invocation.
Correct.
I personally like to use array variables in BASH scripting. They're very hand because they can be spread across multiple lines _without_ using backslashes and by putting a single value on each line, you can easily comment out certain values by commenting the line that contains them within the array initialization.
The problem there is that, in this case, how do you populate the array?
for number in "${numbers[@]}"; do echo $number done
Didn't know about this method of extracting the contents of an array. Noted for later use.
for number in "${numbers[*]}"; do echo $number done
Didn't know this one either, so this is also noted for later use. Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
Randall R Schulz wrote:
On Wednesday 13 February 2008 20:41, David C. Rankin wrote:
Listmates,
I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation.
I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html
It sounds like someone needs to submit some feedback to the author or maintainer of that document.
I'll take care of it. Thanks! -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thursday 14 February 2008 05:41:23 David C. Rankin wrote:
Listmates,
I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation.
I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html
The example give is:
[carol@octarine ~/html] cat html2php.sh #!/bin/bash # specific conversion script for my html files to php LIST="$(ls *.html)" for i in "$LIST"; do NEWNAME=$(ls "$i" | sed -e 's/html/php/') cat beginfile > "$NEWNAME" cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME" cat endfile >> "$NEWNAME" done
This is actually in a tutorial? Wow for i in *; do NEWNAME=${i%html}.php echo beginfile > "$NEWNAME" sed -e '1,25d.........
So I created the following:
#!/bin/bash LIST="$(ls *.zip)" for i in "$LIST"; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0
for i in *.zip; do unzip "$i" -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract done You want to have the quotes around $i to guard against spaces in file names Anders -- Madness takes its toll -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
Anders Johansson wrote:
On Thursday 14 February 2008 05:41:23 David C. Rankin wrote:
Listmates,
I have run into a bash problem with a simple for loop I don't understand and would like input from the gurus to determine if the tldp documentation is in error or if it is me. Safe money says it's me, but here is the situation.
I am using example 9.1.2.2. from the following link to construct a simple for loop to extract a directory full of zip files:
http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_01.html
The example give is:
[carol@octarine ~/html] cat html2php.sh #!/bin/bash # specific conversion script for my html files to php LIST="$(ls *.html)" for i in "$LIST"; do NEWNAME=$(ls "$i" | sed -e 's/html/php/') cat beginfile > "$NEWNAME" cat "$i" | sed -e '1,25d' | tac | sed -e '1,21d'| tac >> "$NEWNAME" cat endfile >> "$NEWNAME" done
This is actually in a tutorial? Wow
for i in *; do NEWNAME=${i%html}.php echo beginfile > "$NEWNAME" sed -e '1,25d.........
So I created the following:
#!/bin/bash LIST="$(ls *.zip)" for i in "$LIST"; do unzip $i -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract echo "Unzipped: $i to ../extract" done exit 0
for i in *.zip; do unzip "$i" -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract done
You want to have the quotes around $i to guard against spaces in file names
Anders
Anders, I found the quotes around "$i" do not work for managing filenames with spaces. The filenames, spaces and all, are pulled in by the LIST="$(ls *.zip)". Quoted or unquoted, it makes no difference, because $i is just the next element in the list. Example: goodfile 001.jpg exists in the list as: goodfile 001.jpg for i $list; do echo "i = $1" done gives: i = goodfile i = 001.jpg regardless. Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_': AFS='\n' for i $list; do Telling the loop not to break on spaces with AFS seems to work like a charm. Are there any better ways? echo "i = $1" done -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Fri, 15 Feb 2008, David C. Rankin wrote:-
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_':
AFS='\n' for i $list; do
^ You're missing an 'in' there.
Telling the loop not to break on spaces with AFS seems to work like a charm. Are there any better ways? echo "i = $1" done
Since you're only using $list to hold the list of file names that are used in the for loop, don't use $list. Assuming you assigned $list using: list="$(ls *.jpg)" this would have the same effect: for i in *.jpg do echo "i = ${i}" done Alternatively, if you must use $list, you can use the following instead: echo "${list}" | \ while read i do echo "i = ${i}" done One last tip: try getting into the habit of wrapping {} around variable names. It comes in handy for figuring out what are variables when you use echo, and it's good at preventing typos from messing them up. E.g. text="some line of text" echo "$text is used for testing" gets you: some line of test is used for testing However, missing out a space: text="some line of text" echo "$textis used for testing" gets you: used for testing whereas putting {} around text: text="some line of text" echo "${text}is used for testing" gets you: some line of textis used for testing While this may not seem important, it helps when debugging, and is required if you're going to use arrays. Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thursday 14 February 2008 23:13, David C. Rankin wrote:
...
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_':
It's "IFS" not "AFS" and you need the "in" keyword as David Bolt mentioned:
IFS='\n' for i in $list; do
Telling the loop not to break on spaces with AFS seems to work like a charm. Are there any better ways? echo "i = $1" done ... David C. Rankin
Randall Schulz -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Fri, 15 Feb 2008, Randall R Schulz wrote:-
On Thursday 14 February 2008 23:13, David C. Rankin wrote:
...
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_':
It's "IFS" not "AFS" and you need the "in" keyword as David Bolt mentioned:
And if the script is more than just a quick one-liner, you should really be saving and restoring the old IFS, or you can end up with some rather difficult to diagnose failures. You can find an example of this is in /etc/init.d/alsasound === start snippet === load_sequencer() { test "$LOAD_SEQUENCER" = "yes" && modprobe -q snd-seq if [ x"$LOAD_SEQUENCER" = xyes -a -r /proc/asound/seq/drivers ]; then OLDIFS="$IFS" IFS="," while read t x c; do /sbin/modprobe $t done < /proc/asound/seq/drivers IFS="$OLDIFS" fi } === end snippet === One interesting aside here is the use of the test: [ x$c = x ] a little later in that script. Why on earth they didn't use this instead is an interesting puzzle: [ -z "$c" ] Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Thursday 14 February 2008 23:13, David C. Rankin wrote:
...
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_':
It's "IFS" not "AFS" and you need the "in" keyword as David Bolt mentioned:
And if the script is more than just a quick one-liner, you should really be saving and restoring the old IFS, or you can end up with some rather difficult to diagnose failures. You can find an example of this is in /etc/init.d/alsasound === start snippet === load_sequencer() { test "$LOAD_SEQUENCER" = "yes" && modprobe -q snd-seq if [ x"$LOAD_SEQUENCER" = xyes -a -r /proc/asound/seq/drivers ]; then OLDIFS="$IFS" IFS="," while read t x c; do /sbin/modprobe $t done < /proc/asound/seq/drivers IFS="$OLDIFS" fi } === end snippet === One interesting aside here is the use of the test: [ x$c = x ] a little later in that script. Why on earth they didn't use this instead is an interesting puzzle: [ -z "$c" ] Regards, David Bolt </quote> That is a workaround for older version of bash and uninitialized variables, I've had to use it many times. -- Best regards, Nick Zeljkovic -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Fri, 15 Feb 2008, Nick Zeljkovic wrote:-
That is a workaround for older version of bash and uninitialized variables, I've had to use it many times.
Must have been a very old version. The oldest one I have access to is bash-2.05b-305.1[0] and that has no problem with uninitialised variables, or the use of -z as a test. Then again, I have always wrapped variables in quotes so any tests I perform won't fail with empty strings. [0] davjam@thargon:~> rpm -qi bash Name : bash Relocations: (not relocatable) Version : 2.05b Vendor: SuSE Linux AG, Nuernberg, Germany Release : 305.1 Build Date: Sat 24 Apr 2004 19:57:34 BST Install date: Mon 01 Nov 2004 21:59:40 GMT Build Host: welles.suse.de Group : System/Shells Source RPM: bash-2.05b-305.1.src.rpm Size : 2401001 License: GPL Signature : DSA/SHA1, Sat 24 Apr 2004 22:00:05 BST, Key ID a84edae89c800aca Packager : http://www.suse.de/feedback URL : http://www.gnu.org/software/bash/bash.html Summary : The GNU Bourne-Again Shell Description : Bash is an sh-compatible command interpreter that executes commands read from standard input or from a file. Bash incorporates useful features from the Korn and C shells (ksh and csh). Bash is intended to be a conformant implementation of the IEEE Posix Shell and Tools specification (IEEE Working Group 1003.2). Authors: -------- Brian Fox <bfox@gnu.org> Chet Ramey <chet@ins.cwru.edu> Distribution: SuSE Linux 9.1 (i586) Regards, David Bolt -- Team Acorn: http://www.distributed.net/ OGR-P2 @ ~100Mnodes RC5-72 @ ~15Mkeys SUSE 10.1 32bit | openSUSE 10.2 32bit | openSUSE 10.3 32bit | openSUSE 11.0a1 SUSE 10.1 64bit | openSUSE 10.2 64bit | openSUSE 10.3 64bit RISC OS 3.6 | TOS 4.02 | openSUSE 10.3 PPC | RISC OS 3.11 -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
That is a workaround for older version of bash and uninitialized variables, I've had to use it many times.
Must have been a very old version. The oldest one I have access to is bash-2.05b-305.1[0] and that has no problem with uninitialised variables, or the use of -z as a test. Then again, I have always wrapped variables in quotes so any tests I perform won't fail with empty strings. [0] davjam@thargon:~> rpm -qi bash Name : bash Relocations: (not relocatable) Version : 2.05b Vendor: SuSE Linux AG, Nuernberg, Germany Release : 305.1 Build Date: Sat 24 Apr 2004 19:57:34 BST Install date: Mon 01 Nov 2004 21:59:40 GMT Build Host: welles.suse.de Group : System/Shells Source RPM: bash-2.05b-305.1.src.rpm Size : 2401001 License: GPL Signature : DSA/SHA1, Sat 24 Apr 2004 22:00:05 BST, Key ID a84edae89c800aca Packager : http://www.suse.de/feedback URL : http://www.gnu.org/software/bash/bash.html Summary : The GNU Bourne-Again Shell Description : Bash is an sh-compatible command interpreter that executes commands read from standard input or from a file. Bash incorporates useful features from the Korn and C shells (ksh and csh). Bash is intended to be a conformant implementation of the IEEE Posix Shell and Tools specification (IEEE Working Group 1003.2). Authors: -------- Brian Fox <bfox@gnu.org> Chet Ramey <chet@ins.cwru.edu> Distribution: SuSE Linux 9.1 (i586) Regards, David Bolt </quote> Yeah, you know, old habits die hard ;) Probably the original manual was written long time ago when that needed to be used. -- Best regards, Nick Zeljkovic -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Fri, Feb 15, 2008 at 03:14:30PM +0000, David Bolt wrote:
On Fri, 15 Feb 2008, Randall R Schulz wrote:-
On Thursday 14 February 2008 23:13, David C. Rankin wrote:
...
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_':
It's "IFS" not "AFS" and you need the "in" keyword as David Bolt mentioned:
And if the script is more than just a quick one-liner, you should really be saving and restoring the old IFS, or you can end up with some rather difficult to diagnose failures. You can find an example of this is in /etc/init.d/alsasound
=== start snippet === load_sequencer() { test "$LOAD_SEQUENCER" = "yes" && modprobe -q snd-seq if [ x"$LOAD_SEQUENCER" = xyes -a -r /proc/asound/seq/drivers ]; then OLDIFS="$IFS" IFS="," while read t x c; do /sbin/modprobe $t done < /proc/asound/seq/drivers IFS="$OLDIFS" fi } === end snippet ===
Within bash one may use in shell functions local IFS to make any change local to the defined shell function only.
One interesting aside here is the use of the test:
[ x$c = x ]
a little later in that script. Why on earth they didn't use this instead is an interesting puzzle:
[ -z "$c" ]
Very old shells without builtin `test' or `[' on very old UNICES may use the /bin/[ program without knowning about -z. Maybe Randall had read some of the shell scripts written on. Werner -- "Having a smoking section in a restaurant is like having a peeing section in a swimming pool." -- Edward Burr -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
David Bolt wrote:
On Fri, 15 Feb 2008, Randall R Schulz wrote:-
On Thursday 14 February 2008 23:13, David C. Rankin wrote:
...
Stumbling around, it seems if you include AFS='\n' it will keep the loop from breaking on spaces by specifying that it only break on newlines and not spaces. So filenames with spaces (all my wife's digital pictures are) this is the only thing I have found to work without extensive character and replacing spaces with '_': It's "IFS" not "AFS" and you need the "in" keyword as David Bolt mentioned:
And if the script is more than just a quick one-liner, you should really be saving and restoring the old IFS, or you can end up with some rather difficult to diagnose failures. You can find an example of this is in /etc/init.d/alsasound
IFS is what I used, don't know how AFS got in there. Yes, it was kind of comical when after running the script I had managed to loose the "ls" command. I'm not entirely sure it was the IFS, but I just logged out and logged back on and all was well. -- David C. Rankin, J.D., P.E. Rankin Law Firm, PLLC 510 Ochiltree Street Nacogdoches, Texas 75961 Telephone: (936) 715-9333 Facsimile: (936) 715-9339 www.rankinlawfirm.com -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
On Friday 15 February 2008 08:13:57 David C. Rankin wrote:
for i in *.zip; do unzip "$i" -d /mnt/nemesis-cfg/home/samba/computer/software/fonts/extract done
You want to have the quotes around $i to guard against spaces in file names
Anders
Anders,
I found the quotes around "$i" do not work for managing filenames with spaces. The filenames, spaces and all, are pulled in by the LIST="$(ls *.zip)". Quoted or unquoted, it makes no difference, because $i is just the next element in the list. Example: goodfile 001.jpg exists in the list as:
goodfile 001.jpg
for i $list; do echo "i = $1" done
gives:
i = goodfile i = 001.jpg
Yes, I know. That's not what I wrote. for i in *.jpg; do echo "i = $i" done i = goodfile 001.jpg forget about the quotes around LIST, or (better still) forget about LIST altogether Anders -- Madness takes its toll -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org
participants (6)
-
Anders Johansson
-
David Bolt
-
David C. Rankin
-
Dr. Werner Fink
-
Nick Zeljkovic
-
Randall R Schulz