Tuesday, October 7, 2008

Spaces in directory names ... I really love you not!

Have I mentioned I really love Python? Have also mention that I really hate Windows? I did not? Well here I go again ... I REALLY HATE WINDOWS. This time the target of my scorn or anger is the stupid spaces in folder names windows users are so apt to give to their folders. It screws my programs and special attention has to be given to quote them to work...

Grrrr, all sorts of funny stuff happen at this stage. I am wondering how the heck I am going to quote the whole filename if I am doing something like below:

import shutil

for file in os.listdir("/home/lowks"):


I tried 'shutil.copy('%s',"/tmp") but it spat out errors at me. Is this because the string is a unicode string? If so how do you convert the file path to a raw string? I really hope if someone has experience doing this to shine some light this way.

Ops ... it seems I made a little error there, it seems to work but not in my longer script. My script basically has to copy a file including it's parent folders into a fail / success directory based on the outcome of running the script. I tried shutil.copytree but it does not work and fails silently, which prompted my spaces-in-directory-name hate. I am wondering aloud here there must be an easier way of doing this, a one liner thing.

I think also I have found the error with my script. It is still a space related issue where if there is a space in the folder name, then it automatically treats the last string as a file name and shutil will bomb out when it tries to open up that file for copying or moving, like something below:

Traceback (most recent call last):
File "process.py", line 321, in
File "D:\python25\lib\shutil.py", line 80, in copy
copyfile(src, dst)
File "D:\python25\lib\shutil.py", line 46, in copyfile
fsrc = open(src, 'rb')
IOError: [Errno 13] Permission denied: u'C:\\import2\\testing folder'

In the case above, the 'testing folder' is actually a folder but shutil have interpreted the 'folder' as the filename hence the exception.

Ah ask and ye shall receive, in windows there is a short file name for all files for example C:\Program Files is equals to C:\Progra~1 or something to that effect. This same short filename can be used in python if you use the win32api, in a one liner like this:

import win32api

long_file_name='C:\Program Files\I am a file'

This works. If you are incline to read more about this go here.


Robert Kern said...

It's not because the name has spaces. It's because you simply added the name of the file to the name of the directory without using a directory separator. Use os.path.join() instead.

Michael Foord said...

Windows aside, any program that can't handle spaces in paths is broken... :-)

Carl Trachte said...

Michael, you are correct.
Still, I agree with the author, I hate spaces in directory names as well.
Program Files - ugh!

owf said...

Mr Kern is correct. I've been using Python for years with filenames with space in on Linux, OS X and Windows and they've NEVER been the problem.

You needn't worry about backslashes either--Python automatically converts forward slashes to backslashes on Windows when dealing with files.

os.path.join() is great because you don't have to worry about whether your paths have trailing slashes or not.

for aFile in os.listdir(aDirectory):
->aPath = os.path.join(aDirectory, aFile)
->shutil.copy(aPath, ...)

A handy idiom for working with filenames in the shell is:
os.environ["myfile"] = aFile
os.system('mv "$myfile" ../')

The shell will take care of all the escaping for you.