How to create a filename with a trailing period in Windows? - python

How does one work with filenames that end in a period in Python? According to MSDN's site, such filenames are valid in Windows, but whenever I try to create one in Python, it removes the final period. I even tried creating a raw file descriptor with os.open, but it still removes the period.
For example, this will create a file simply named 'test'
os.open('test.', os.O_CREAT | os.O_WRONLY, 0777)
Edit: Here is the exact quote
About spaces and dots in filenames and directories. The limits are
in the windows shell -- not in Windows or NT. Using 'bash', you can
create files with spaces (or dots), both, at the beginning and end of
a filename. You can then list and open those files in explorer, and
you can 'list' them in the shell (cmd.exe), but you won't necessarily
be able to open them from the shell (especially trailing spaces and
dots).

I figured out how to do this. Apparently, passing a normal filename will strip the period even when calling the Win API directly from C. In order to create the weird filenames, you must use the \\?\ prefix (this also disables relative paths and slash conversion).
open('\\\\?\\C:\\whatever\\test.','w')
It's ugly and nonportable, but it works.

The \\?\ syntax also works with cmd.exe:
dir>"\\?\C:\whatever\test."

Windows will strip the final trailing period, assuming it is the delimiter between a filename and a blank extension. Try using two periods.

Related

How to use Popen to open a file with space in its name with default program in windows? [duplicate]

This question already has an answer here:
Using subprocess.Popen (shell=True) with windows folders
(1 answer)
Closed 2 years ago.
The following code can open the test.txt file with notepad
subprocess.Popen(['start','test.txt'],shell=True)
But this won't open a file with a space in its name like 'the test.txt'.
I've tried using raw string(r'...'), double quote on cmd, '%20' to substitute the space, but none of that works.
Passing a list of arguments with shell=True happens to generally work on Windows, but is really never correct. Of course, start is a shell (cmd) command, so you need a shell here; but then, you also need to quote the string for the shell.
subproces.run('start "the test.txt"', shell=True)
Notice also that I switched to subprocess.run(); you generally want to avoid raw Popen whenever you can, as also suggested in the documentation.
It's much easier to rename the file with an underscore or dash etc.
I had a similar issue once with a client. I'm fairly certain we concluded by renaming by hand all of the necessary files to replace a space with an underscore.
Unless python have released a patch (or indeed, I was oblivious), I think it may be impossible.
Python reads a space and goes "okay, thats that command, what's next?" and then reads whatever follows the space, excluding certain things like string variables.
Take these lines
import os
os.system("start EXCEL.EXE my workbook.xlsb")
Python of course imports the os module here, then in line two it runs the os.system command with the parameters; start, EXCEL.EXE, my, workbook.xlsb
in fact it doesn't, once it reaches the filename "my" without an extension it quits and throws an error in the shell.

Does os.path.sep affect the tarfile module?

Is the path separator employed inside a Python tarfile.TarFile object a '/' regardless of platform, or is it a backslash on Windows?
I basically never touch Windows, but I would kind of like the code I'm writing to be compatible with it, if it can be. Unfortunately I have no Windows host on which to test.
A quick test tells me that a (forward) slash is always used.
In fact, the tar format stores the full path of each file as a single string, using slashes (try looking at a hex dump), and python just reads that full path without any modification. Likewise, at extraction time python hard-replaces slashes with the local separator (see TarFile._extract_member).
... which makes me think that there are surely some nonconformant implementations of tar for Windows that create tarfiles with backslashs as separators!?

Can you use os.path.exists() on a file that starts with a number?

I have a set of files named 16ID_#.txt where # represents a number. I want to check if a specific file number exists, using os.path.exists(), before attempting to import the file to python. When I put together my variable for the folder where the files are, with the name of the file (e.x.: folderpath+"\16ID_#.txt"), python interprets the "\16" as a music note.
Is there any way I can prevent this, so that folderpath+"\16ID_#.txt" is interpreted as I want it to be?
I cannot change the names of the files, they are output by another program over which I have no control.
You can use / to build paths, regardless of operating system, but the correct way is to use os.path.join:
os.path.exists(os.path.join(folderpath, "16ID_#.txt"))
I get these are windows \paths. Maybe the problem is that you need to escape the backslash, because \16 could be interpreted as a special code. So maybe you need to put \\16 instead of \16.

Specifying filename in os.system call from python

I am creating a simple file in python to reorganize some text data I grabbed from a website. I put the data in a .txt file and then want to use the "tail" command to get rid of the first 5 lines. I'm able to make this work for a simple filename shown below, but when I try to change the filename (to what I'd actually like it to be) I get an error. My code:
start = 2010
end = 2010
for i in range(start,end+1)
year = str(i)
...write data to a file called file...
teamname=open(file).readline() # want to use this in the new filename
teamfname=teamname.replace(" ","") #getting rid of spaces
file2 = "gotdata2_"+year+".txt"
os.system("tail -n +5 gotdata_"+year+".txt > "+file2)
The above code works as intended, creating file, then creating file2 that excludes the first 5 lines of file. However, when I change the name of file2 to be:
file2 = teamfname+"_"+year+".txt"
I get the error:
sh: line 1: _2010.txt: command not found
It's as if the end of my file2 statement is getting chopped off and the .txt part isn't being recognized. In this case, my code outputs a file but is missing the _2010.txt at the end. I've double checked that both year and teamfname are strings. I've also tried it with and without spaces in the teamfname string. I get the same error when I try to include a os.system mv statement that would rename the file to what I want it to be, so there must be something wrong with my understanding of how to specify the string here.
Does anyone have any ideas about what causes this? I haven't been able to find a solution, but I've found this problem difficult to search for.
Without knowing what your actual strings are, it's impossible to be sure what the problem is. However, it's almost certainly something to do with failing to properly quote and/or escape arguments for the command line.
My first guess would be that you have a newline in the middle of your filename, and the shell is truncating the command at the newline. But I wouldn't bet too heavily on that. If you actually printed out the repr of the pathname, I could tell you for sure. But why go through all this headache?
The solution to almost any problem with os.system is to not use os.system.
If you look at the docs, they even tell you this:
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function. See the Replacing Older Functions with the subprocess Module section in the subprocess documentation for some helpful recipes.
If you use subprocess instead of os.system, you can avoid the shell entirely. You can also pass arguments as a list instead of trying to figure out how to quote them and escape them properly. Which would completely avoid the exact problem you're having.
For example, if you do this:
file2 = "gotdata2_"+year+".txt"
with open(file2, 'wb') as f:
subprocess.check_call(['tail', '-n', '+5', "gotdata_"+year+".txt"], stdout=f)
Then, if you change that first line to this:
file2 = teamfname+"_"+year+".txt"
It will still work even if teamfname has a space or a quote or another special character in it.
That being said, I'm not sure why you want to use tail in the first place. You can skip the first 5 lines just as easily directly in Python.

how to check for platform incompatible folder (file) names in python

I would like to be able to check from python if a given string could be a valid cross platform folder name - below is the concrete problem I ran into (folder name ending in .), but I'm sure there are some more special cases (e.g.: con, etc.).
Is there a library for this?
From python (3.2) I created a folder on Windows (7) with a name ending in dot ('.'), e.g. (without square brackets): [What I've done on my holidays, Part II.]
When the created folder was ftp'd (to linux, but I guess that's irrelevant), it did not have the dot in it anymore (and in return, this broke a lot of hyperlinks).
I've checked it from the command line, and it seems that the folder doesn't have the '.' in the filename
mkdir tmp.
dir
cd tmp
cd ..\tmp.
Apparently, adding a single dot at the end of the folder name is ignored, e.g.:
cd c:\Users.
works just as expected.
Nope there's sadly no way to do this. For windows you basically can use the following code to remove all illegal characters - but if someone still has a FAT filesystem you'd have to handle these too since those are stricter. Basically you'll have to read the documentation for all filesystem and come up with a complete list. Here's the NTFS one as a starting point:
ILLEGAL_NTFS_CHARS = "[<>:/\\|?*\"]|[\0-\31]"
def __removeIllegalChars(name):
# removes characters that are invalid for NTFS
return re.sub(ILLEGAL_NTFS_CHARS, "", name)
And then you need some "forbidden" name list as well to get rid of COM. Pretty much a complete mess that.. and that's ignoring linux (although there it's pretty relaxed afaik)
Do not end a file or directory name with a space or a period. Although
the underlying file system may support such names, the Windows shell
and user interface does not.
http://msdn.microsoft.com/en-us/library/aa365247.aspx#naming_conventions
That page will give you information about other illegal names too, for Windows that is. Including CON as you said your self.
If you respect those (seemingly harsh) rules, I think you'll be safe on Linux and most other systems too.

Categories