[ale] Problems w/ mv and sed

David S. Jackson dsj at sylvester.dsj.net
Tue Dec 24 10:52:41 EST 2002


On Tue, Dec 24, 2002 at 01:29:39AM -0500 Stephen Touset <stephen at touset.dyndns.org> wrote:
> I'll try that in a sec, but I'm wondering why my methods didn't work.
> The sed command I issued should have (and did) escape out the spaces.

If the filenames are properly quoted, the spaces don't need escaping.
And if you escape the quotes, then bash may not see them and it's just
as if they weren't there.

Also, the delimiter for "for" loops is a space.  If there are any spaces
in your files that bash ever sees, "for" will treat them as delimited
arguments in the forloop, and mv will therefore see them as separate
arguments rather than a single argument whose string contains a space.
Hence, careful quoting is key here.  For operations on files with a
space, a while/read loop, or equivalent, is sometimes better than a for
loop, being extra sensitive to spaces, although a for loop can still
work.

This goes for not just spaces, but any metacharacter in filenames that
bash might otherwise misinterpret.

> The other one I tried simply surrounded the filenames with quotes. Both
> of those methods worked when I typed them in manually, checking against
> the actual command that the script I wrote ended up calling (from the
> echo'd version of it). Why did neither of those approaches work?
[...]
> > >>>mv: when moving multiple files, last argument must be a directory
> > >>>Try `mv --help' for more information.

If mv gives you the "last argument must be a directory" error, that's
telling you it's seeing more than two arguments, right?  That should
tell you that it's interpreting those extra spaces as delimiters in a
for loop rather than as two single arguments to mv whose string values
contain spaces.  That means it's a quoting problem.

Whether you are using either sed or a bash builtin, the for loop is
eager to interpret those spaces as delimiters.  

There's a precidence in how characters are interpreted on the
commandline:

1. Split everything into tokens (meaningful characters and/or strings).
2. Check 1st token--is it opening keyword or error?
3. If not a keyword, is it an alias? if so tokenize, if not parse
further.
4. Expand braces
5. Expand tildes
6. Expand parameters
7. Expand command substitution
8. Perform arithmetic substituion
9. Do word splitting
10. Do pathname expansion
11. Do command lookup (builtin, function, external command)
12. Run command (eval) 

Any of these will send results back into "split everything into tokens"
above if nested goodies are parsed out.

> Stephen Touset
> 
> On Mon, 2002-12-23 at 23:31, Geoffrey wrote:
> > Bingo, the first file contains an embedded space.  The space between the 
> >   'To' and 'Zanarkand'.  This is the problem.  Try this:
> > 
> > for fn in *.OK;do
> > 	mv "$fn" "${fn%.OK}"
> > done

Here's an example of how even a for loop with proper quoting can be made
to work with filenames with spaces.

My advice would be to get a good bash book, read through it, and pay
attention to the parts you stumble on.  You obviously are no newbie, but
bashisms can stump even old timers.  :-)  I still have to keep a bash
book handy, and it gets well used, let me tellya.  Hehe.

-- 
David S. Jackson                        dsj at dsj.net
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
I should have been a country-western singer.
After all, I'm older than most western countries.
		-- George Burns

 PGP signature




More information about the Ale mailing list