On 10Dec2008 15:05, Robert Wuest <rwuestfc@xxxxxxxxx> wrote: | Spaces have always been one of my pet peeves and I find this discussion | rather interesting. Spaces don't belong in filenames and they make | script writing a pain. I'm going to include a script I wrote a long | time ago to handle the problem of junk characters in music files. Even | buying music online from Amazon will get you spaces in filenames :( | | I remember messing with this little script quite a bit before it worked. | One lesson I learned writing this was to use lot's of double quotes. | The script replaces spaces (and other things) in filenames. I just put | it up here as an example since it's pretty short. I seem to use it a | lot. | | The main for loop is: | | for i in *; do | fixname "$i" | done | | Notice the quotes around "$i". They're important. [...] | function fixname() | { | newname=`echo $1 | \ Because the $1 is unquoted here you probably don't need the "+" in the regexps. But you probably should quote $1 because of this: [/Users/cameron]fleet*> x='t*' [/Users/cameron]fleet*> echo "$x" t* [/Users/cameron]fleet*> echo $x test.txt them tmp i.e. if $x is not quoted then glob characters in a filename will get expanded (supposing you have a name like "t*", and some other files starting with "t"). | sed -r \ | -e "s/[ ]+/_/g" \ | -e "s/[_]+/_/g" \ | -e "s/'//g" \ | -e "s/[+]//g" \ | -e "s/,//g" \ | -e "s/_-_/-/g" \ | -e "s/\&/and/g"`; | # only do rename if the name is changed | if [ \"$1\" != \"${newname}\" ]; then You don't need to backslash the "s in this comparison. | echo mv \"$1\" \"${newname}\" This is actually dangerous. By leaving the (expanded) $1 in double quotes, it is subject to parameter and command substitution in the shell that runs the commands you generate. For example, supposing I ship you a file whole name contains: `rm -rf $HOME` That _will_ get through your script, and _will_ run the rm command in the subshell. In both the $1 and $newname parts. But it gets better. Even though you remove all single quotes form $newname, and are thus safe to emit: mv ..... '$newname' the $1 is still unsafe, and cannot easily be made safe. (Actually, bash's "printf %q" formatter may do the trick for you, and since you're already in nonportable GNU sed land, you may as well step right in with nonportable bash too:-) Personally, I would change the script mode. Instead of trying to emit safe shell syntax for piping to "sh", I would instead give it two modes of operation. Default is to recite commands and a -x option would make it actually move files around. Like this: setx() { ( set -x "$@" ) } trace=echo # handle leading -x option if [ "x$1" = x-x ] then shift trace=setx fi and then down where you emit the mv commands go: $trace mv "$1" "$newname" which should be robust against weird names in $1 or $newname. BTW, have you worried about having mv move a "bad" filename onto an already existing "good" name? A "mv -i" might avoid a little pain. | else | echo "# \"$1\" and \"${newname}\" are the same file" | fi | } | | if [ "$#" == "0" ]; then No quotes needed here, and "==" is not a test notation. You want "=" (string comparison) or "-eq" (numeric comparison). | for i in *; do | fixname "$i" | done | else | while [ "z$1" != "z" ]; do | fixname "$1" | shift | done This loop is better written: for i; do fixname "$i" done otherwise running your script like this: your-script a b c "" d e f will only operate on the first 3 names. Besides, the "for i; do" notation is shorter and clearer (once you know that leaving off the "in" clause iterates over the command line arguments). And all to frequently you see this in scripts: for i in $*; do which has the usual "spaces in words" trouble we're all working around here. Personally, I strive to be robust against weird names in my code, to avoid having to play rename games like yours. I do have renaming scripts like your for much the same reason you do, though. Cheers, -- Cameron Simpson <cs@xxxxxxxxxx> DoD#743 http://www.cskk.ezoshosting.com/cs/ Lady, have you ever seen a cat skeleton in a tree? - Kevin Dunn -- fedora-list mailing list fedora-list@xxxxxxxxxx To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list Guidelines: http://fedoraproject.org/wiki/Communicate/MailingListGuidelines