Python wrapper for extended filesystem attributes with dict-like interface
Simple function-based API for direct extended attribute operations without creating xattr objects. These functions are ideal for one-off operations and provide a straightforward interface for basic extended attribute manipulation.
Retrieve the value of a single extended attribute from a file.
def getxattr(f, attr, symlink=False):
"""
Get extended attribute value from file.
Parameters:
- f: str path, int file descriptor, or file-like object
- attr: str, attribute name
- symlink: bool, if True don't follow symbolic links
Returns:
bytes: attribute value
Raises:
IOError: filesystem error or attribute not found
"""Usage Examples:
import xattr
# Get attribute from file path
description = xattr.getxattr('/path/to/file', 'user.description')
print(description) # b'File description'
# Get attribute from symlink (not target)
link_attr = xattr.getxattr('/path/to/symlink', 'user.link_info', symlink=True)
# Get attribute using file descriptor
with open('/path/to/file', 'rb') as f:
title = xattr.getxattr(f.fileno(), 'user.title')Set the value of a single extended attribute on a file.
def setxattr(f, attr, value, options=0, symlink=False):
"""
Set extended attribute value on file.
Parameters:
- f: str path, int file descriptor, or file-like object
- attr: str, attribute name
- value: bytes, attribute value (must be bytes)
- options: int, operation flags (XATTR_CREATE, XATTR_REPLACE, etc.)
- symlink: bool, if True don't follow symbolic links
Raises:
IOError: filesystem error, permission denied, or flag constraints
TypeError: value is not bytes
"""Usage Examples:
import xattr
# Set basic attribute
xattr.setxattr('/path/to/file', 'user.description', b'My important file')
# Set with create flag (fail if exists)
xattr.setxattr('/path/to/file', 'user.id', b'12345', xattr.XATTR_CREATE)
# Set with replace flag (fail if doesn't exist)
xattr.setxattr('/path/to/file', 'user.version', b'2.0', xattr.XATTR_REPLACE)
# Set on symlink itself
xattr.setxattr('/path/to/symlink', 'user.link_type', b'shortcut', symlink=True)
# Set using file object
with open('/path/to/file', 'r+b') as f:
xattr.setxattr(f, 'user.modified_by', b'script')Retrieve a list of all extended attribute names for a file.
def listxattr(f, symlink=False):
"""
List all extended attribute names for file.
Parameters:
- f: str path, int file descriptor, or file-like object
- symlink: bool, if True don't follow symbolic links
Returns:
tuple[str, ...]: attribute names with appropriate namespace prefixes
Raises:
IOError: filesystem error
"""Usage Examples:
import xattr
# List all attributes
attrs = xattr.listxattr('/path/to/file')
print(attrs) # ('user.description', 'user.title', 'user.version')
# List attributes on symlink itself
link_attrs = xattr.listxattr('/path/to/symlink', symlink=True)
# List using file descriptor
with open('/path/to/file', 'rb') as f:
attrs = xattr.listxattr(f.fileno())
for attr in attrs:
value = xattr.getxattr(f.fileno(), attr)
print(f"{attr}: {value}")Remove a single extended attribute from a file.
def removexattr(f, attr, symlink=False):
"""
Remove extended attribute from file.
Parameters:
- f: str path, int file descriptor, or file-like object
- attr: str, attribute name to remove
- symlink: bool, if True don't follow symbolic links
Raises:
IOError: filesystem error or attribute not found
"""Usage Examples:
import xattr
# Remove attribute
xattr.removexattr('/path/to/file', 'user.old_description')
# Remove from symlink itself
xattr.removexattr('/path/to/symlink', 'user.temp_attr', symlink=True)
# Remove using file object
with open('/path/to/file', 'r+b') as f:
xattr.removexattr(f, 'user.cache_data')
# Remove all user attributes
attrs = xattr.listxattr('/path/to/file')
for attr in attrs:
if attr.startswith('user.'):
xattr.removexattr('/path/to/file', attr)Comprehensive example showing typical extended attribute operations using convenience functions.
import xattr
# File path
filepath = '/path/to/document.txt'
# Set multiple attributes
metadata = {
'user.title': b'Important Document',
'user.author': b'John Doe',
'user.version': b'1.0',
'user.tags': b'work,important,draft'
}
for attr, value in metadata.items():
xattr.setxattr(filepath, attr, value)
# List and display all attributes
print("Extended attributes:")
for attr in xattr.listxattr(filepath):
value = xattr.getxattr(filepath, attr)
print(f" {attr}: {value.decode('utf-8', errors='replace')}")
# Update specific attribute
xattr.setxattr(filepath, 'user.version', b'1.1', xattr.XATTR_REPLACE)
# Check if attribute exists and get value
try:
description = xattr.getxattr(filepath, 'user.description')
print(f"Description: {description}")
except IOError:
print("No description set")
xattr.setxattr(filepath, 'user.description', b'Default description')
# Clean up - remove temporary attributes
temp_attrs = [attr for attr in xattr.listxattr(filepath)
if 'temp' in attr.lower()]
for attr in temp_attrs:
xattr.removexattr(filepath, attr)Convenience functions raise IOError/OSError for various filesystem conditions:
import xattr
try:
# This will raise IOError if attribute doesn't exist
value = xattr.getxattr('/path/to/file', 'user.nonexistent')
except IOError as e:
if e.errno == 61: # ENODATA on Linux, ENOATTR on macOS
print("Attribute does not exist")
else:
print(f"Filesystem error: {e}")
try:
# This will raise TypeError if value is not bytes
xattr.setxattr('/path/to/file', 'user.test', 'not bytes')
except TypeError:
print("Values must be bytes")
xattr.setxattr('/path/to/file', 'user.test', b'correct bytes value')Install with Tessl CLI
npx tessl i tessl/pypi-xattr