Why does Python give OSError: [Errno 36] File name too long for filename shorter than filesystem's limit?
I've found a solution. It turns out that I'm not dealing with pure ext4---it's actually ecryptfs layered atop ext4, carried over from a previous Ubuntu install. As suggested in an unaccepted answer to this related question the ecryptfs layer imposes a limit of 143 characters to the filename length. A definitive answer to the file name length limit under ecryptfs can be found here.
Ubuntu encrypted home directory | Errno 36 File Name too long
The fact that the filename that's too long starts with '.cache/www.example.com'
explains the problem.
httplib2
optionally caches requests that you make. You've enabled caching, and you've given it .cache
as the cache directory.
The easy solution is to put the cache directory somewhere else.
Without seeing your code, it's impossible to tell you how to fix it. But it should be trivial. The documentation for FileCache
shows that it takes a dir_name
as the first parameter.
Or, alternatively, you can pass a safe
function that lets you generate a filename from the URI, overriding the default. That would allow you to generate filenames that fit within the 144-character limit for Ubuntu encrypted fs.
Or, alternatively, you can create your own object with the same interface as FileCache
and pass that to the Http
object to use as a cache. For example, you could use tempfile
to create random filenames, and store a mapping of URLs to filenames in an anydbm
or sqlite3
database.
A final alternative is to just turn off caching, of course.
What characters are forbidden in Windows and Linux directory names?
A “comprehensive guide” of forbidden filename characters is not going to work on Windows because it reserves filenames as well as characters. Yes, characters like*
"
?
and others are forbidden, but there are a infinite number of names composed only of valid characters that are forbidden. For example, spaces and dots are valid filename characters, but names composed only of those characters are forbidden.
Windows does not distinguish between upper-case and lower-case characters, so you cannot create a folder named A
if one named a
already exists. Worse, seemingly-allowed names like PRN
and CON
, and many others, are reserved and not allowed. Windows also has several length restrictions; a filename valid in one folder may become invalid if moved to another folder. The rules for
naming files and folders
are on the Microsoft docs.
You cannot, in general, use user-generated text to create Windows directory names. If you want to allow users to name anything they want, you have to create safe names like A
, AB
, A2
et al., store user-generated names and their path equivalents in an application data file, and perform path mapping in your application.
If you absolutely must allow user-generated folder names, the only way to tell if they are invalid is to catch exceptions and assume the name is invalid. Even that is fraught with peril, as the exceptions thrown for denied access, offline drives, and out of drive space overlap with those that can be thrown for invalid names. You are opening up one huge can of hurt.
Find all files in a directory with extension .txt in Python
You can use glob
:
import glob, os
os.chdir("/mydir")
for file in glob.glob("*.txt"):
print(file)
or simply os.listdir
:
import os
for file in os.listdir("/mydir"):
if file.endswith(".txt"):
print(os.path.join("/mydir", file))
or if you want to traverse directory, use os.walk
:
import os
for root, dirs, files in os.walk("/mydir"):
for file in files:
if file.endswith(".txt"):
print(os.path.join(root, file))
How do I get file creation and modification date/times?
In Python 3.4 and above, you can use the object oriented pathlib module interface which includes wrappers for much of the os module. Here is an example of getting the file stats.
>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}' # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)
For more information about what os.stat_result
contains, refer to the documentation. For the modification time you want fname.stat().st_mtime
:
>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime, tz=datetime.timezone.utc)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)
If you want the creation time on Windows, or the most recent metadata change on Unix, you would use fname.stat().st_ctime
:
>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime, tz=datetime.timezone.utc)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)
This article has more helpful info and examples for the pathlib module.
Best way to resolve file path too long exception
As the cause of the error is obvious, here's some information that should help you solve the problem:
See this MS article about Naming Files, Paths, and Namespaces
Here's a quote from the link:
Maximum Path Length Limitation In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length
for a path is MAX_PATH, which is defined as 260 characters. A local
path is structured in the following order: drive letter, colon,
backslash, name components separated by backslashes, and a terminating
null character. For example, the maximum path on drive D is "D:\some
256-character path string<NUL>" where "<NUL>" represents the invisible
terminating null character for the current system codepage. (The
characters < > are used here for visual clarity and cannot be part of
a valid path string.)
And a few workarounds (taken from the comments):
There are ways to solve the various problems. The basic idea of the solutions listed below is always the same: Reduce the path-length in order to have path-length + name-length < MAX_PATH
. You may:
- Share a subfolder
- Use the commandline to assign a drive letter by means of SUBST
- Use AddConnection under VB to assign a drive letter to a path
Related Topics
How to Cleanly Kill Subprocesses in Python
Which Command to Use for Checking Whether Python Is 64Bit or 32Bit
Subprocess.Popen(): Oserror: [Errno 8] Exec Format Error in Python
Error with Igraph Library - Deprecated Library
How to Determine Pid of Process Started via Os.System
Why Does Python "Preemptively" Hang When Trying to Calculate a Very Large Number
How to Make Python Script Press 'Enter' When Prompted on Shell
Where Does Python Tempfile Writes Its Files
Python: What Are the Nearest Linux and Osx Equivalents of Winsound.Beep
Trying to Import Pypyodbc Module Gives Error 'Odbc Library Is Not Found. Is Ld_Library_Path Set'
Writing to Shared Memory in Python Is Very Slow
How to Handle Os.System Sigkill Signal Inside Python
Syntax Error Near Unexpected Token '(' Python Script
Python 2.7 Cx_Freeze: Importerror: No Module Named _Startup_