Substring functions

Martin von Loewis loewis at informatik.hu-berlin.de
Fri Feb 2 17:45:47 EST 2001


dnedrow at usa.net writes:

> The are two functions (is that even the term?)

Sure. What you got are functions. 

> def shellProtect(file):
>   """Protects a filename against shell interpretation.
>   This is done by putting the name in single quotes, and by
>   escaping single quotes in the filename.
>   """
>   return "'%s'" % string.replace(file, "'", "'\\''")
> 
> 
> def mv(self, src, dest):
>   """Shorthand for the pattern trace('mv...);os.system("mv...)."""
>   self.system("mv %s %s" % (shellProtect(src), shellProtect(dest)))

As a side note: Isn't os.rename good enough? On Unix, os.rename won't
work across filesystem boundaries, but some versions of mv will; if
you can exclude that case, os.rename is faster and more reliable than
invoking a shell.

> Basically, mv() is called with source and destination parameters. These
> are quoted via shellProtext() and then passed as input parameters for the
> Unix mv command.
> 
> E.g. if src=/usr/tmp/1/* and dest=/usr/tmp/2, the mv command issued by
> calling mv() above would be:
> 
>   mv '/usr/tmp/1/*' '/usr/tmp/2'
> 
> Unfortunately, a wildcard doesn't work when quoted as above. How do I
> check for an * at the end of the string and quote the input as
>   '/usr/tmp/1/'*
> rather than
>   '/usr/tmp/1/*'
> 
> Any pointers would be appreciated.

Again, I suggest to operate differently. glob.glob will expand
wildcards, and just leave the name as-is if it is a non-pattern valid
file name (actually, it returns a list of file names in either case).

It turns out that os.rename wants the target filename; it doesn't
automatically generate a file name if the target is a directory. That
is where glob.glob1 helps.

So to do the equivalent of your move, I'd do

import os,glob
srcdir = "/usr/tmp/1"
dstdir = "/usr/tmp/2"
for srcfile in glob.glob1(srcdir,"*"):
  src = os.path.join(srcdir,srcfile)
  dst = os.paht.join(dstdir,srcfile)
  os.rename(src, dst)

In addition, if the only pattern you care about is "*" (i.e. all
files), then

for srcfile in os.listdir(srcdir):
  ...

is even better: it is faster, clearer to read, and it will catch
dotfiles (.foo) in /usr/tmp/1 whereas * won't.

I don't know whether you have to support a single move-all-files
operation or whether this is just a special case of something more
general, so I can't advise a "best" solution.

Regards,
Martin



More information about the Python-list mailing list