Re: For Loops and Space in Names



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



Relevant Pages

  • Re: getting rid of filenames with whitespaces
    ... >> i'm using a Linux system running Samba as a filestore for a Windows client. ... >> whitespaces within the filenames. ... >> problem, but since some Unix commands cannot handle such files properly, ... >> a script to perform this task. ...
    (comp.os.linux.misc)
  • Re: FTP and MGET.
    ... How I do this is to direct the FTP output to an output file, then read it in to see all the filenames. ... The following example shows how to do FTP scripting and override so the input script and output script are directed to a file. ... I would need it for the copy commands that will follow in my ...
    (comp.sys.ibm.as400.misc)
  • Re: Filename too long when transferring computers
    ... If you're using the command prompt COPY or XCOPY commands, ... that any imbedded spaces in folders or filenames bother the command ... and destination addresses with double-quotes, ...
    (microsoft.public.windowsxp.general)
  • Re: Exiting os.spawnvs subroutine
    ... Main script: ... # Define arguments for subprocess ... filenames = os.listdir ... print "Successfully contoured at 100 meter interval!" ...
    (comp.lang.python)
  • Re: Iterations
    ... > My users tend to invite a lot of spyware. ... > large portions of a script for each file. ... instead of running this code at each individual workstation that you ... >> filenames so much as specific files, as you are looking only in the root ...
    (microsoft.public.windows.server.scripting)