Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/pyinfra-dev/pyinfra/llms.txt

Use this file to discover all available pages before exploring further.

File facts provide information about files, directories, and filesystem contents on target hosts.

File Information

File

Get detailed information about a single file or directory:
from pyinfra import host
from pyinfra.facts.files import File

file_info = host.get_fact(File, path="/etc/hosts")

if file_info:
    print(f"Size: {file_info['size']} bytes")
    print(f"Owner: {file_info['user']}:{file_info['group']}")
    print(f"Mode: {file_info['mode']}")
    print(f"Modified: {file_info['mtime']}")
else:
    print("File does not exist")
Parameters:
  • path (str, required) - Path to file or directory
Returns: dict | None - File information or None if file doesn’t exist Dict keys:
  • user (str) - Owner username
  • group (str) - Group name
  • mode (int) - Permissions as octal (e.g., 755)
  • size (int) - File size in bytes
  • mtime (datetime | None) - Modification time
  • atime (datetime | None) - Access time
  • ctime (datetime | None) - Change time
  • type (str) - File type: “file”, “directory”, “link”, “block”, “character”, “socket”, “fifo”
  • link_target (str | None) - Target path for symbolic links

Directory

Get list of files in a directory:
from pyinfra.facts.files import Directory

files = host.get_fact(Directory, path="/etc/nginx")

if files:
    print(f"Files in /etc/nginx: {', '.join(files)}")
    for filename in files:
        print(f"  - {filename}")
Parameters:
  • path (str, required) - Path to directory
Returns: list[str] | None - List of filenames, or None if directory doesn’t exist
Returns just filenames, not full paths. Use os.path.join() to build full paths.
Get the target of a symbolic link:
from pyinfra.facts.files import Link

target = host.get_fact(Link, path="/usr/bin/python")

if target:
    print(f"Link points to: {target}")
    # Returns: "/usr/bin/python3.10"
Parameters:
  • path (str, required) - Path to symbolic link
Returns: str | None - Target path, or None if not a link or doesn’t exist

File Contents

FindInFile

Search for a pattern in a file:
from pyinfra.facts.files import FindInFile

# Search for pattern
matches = host.get_fact(
    FindInFile,
    path="/etc/ssh/sshd_config",
    pattern="PermitRootLogin",
)

if matches:
    for line in matches:
        print(f"Found: {line}")
Parameters:
  • path (str, required) - Path to file
  • pattern (str, required) - Pattern to search for (plain text or regex)
Returns: list[str] | None - Matching lines, or None if file doesn’t exist

FindFiles

Find files matching a pattern:
from pyinfra.facts.files import FindFiles

# Find all .conf files
conf_files = host.get_fact(
    FindFiles,
    path="/etc/nginx",
    pattern="*.conf",
)

for file_path in conf_files:
    print(f"Found config: {file_path}")
Parameters:
  • path (str, required) - Directory to search in
  • pattern (str, required) - Filename pattern (glob style)
Returns: list[str] - List of matching file paths Find symbolic links in a directory:
from pyinfra.facts.files import FindLinks

links = host.get_fact(FindLinks, path="/usr/bin")

for link_path in links:
    print(f"Link: {link_path}")
Parameters:
  • path (str, required) - Directory to search
Returns: list[str] - List of symbolic link paths

FindDirectories

Find subdirectories:
from pyinfra.facts.files import FindDirectories

dirs = host.get_fact(FindDirectories, path="/var/log")

for dir_path in dirs:
    print(f"Directory: {dir_path}")
Parameters:
  • path (str, required) - Directory to search
Returns: list[str] - List of subdirectory paths

File Hashes

Sha1File

Get SHA1 hash of a file:
from pyinfra.facts.files import Sha1File

sha1 = host.get_fact(Sha1File, path="/etc/hosts")
print(f"SHA1: {sha1}")
# Returns: "a1b2c3d4e5f6..."
Parameters:
  • path (str, required) - Path to file
Returns: str | None - SHA1 hash, or None if file doesn’t exist

Sha256File

Get SHA256 hash of a file:
from pyinfra.facts.files import Sha256File

sha256 = host.get_fact(Sha256File, path="/etc/hosts")
print(f"SHA256: {sha256}")
Parameters:
  • path (str, required) - Path to file
Returns: str | None - SHA256 hash, or None if file doesn’t exist

Md5File

Get MD5 hash of a file:
from pyinfra.facts.files import Md5File

md5 = host.get_fact(Md5File, path="/etc/hosts")
print(f"MD5: {md5}")
Parameters:
  • path (str, required) - Path to file
Returns: str | None - MD5 hash, or None if file doesn’t exist

File System

BlockDevices

Get list of block devices:
from pyinfra.facts.files import BlockDevices

devices = host.get_fact(BlockDevices)

for device in devices:
    print(f"Device: {device}")
    # Returns: "/dev/sda", "/dev/sdb", etc.
Returns: list[str] - List of block device paths

DiskUsage

Get disk usage information:
from pyinfra.facts.files import DiskUsage

usage = host.get_fact(DiskUsage, path="/")

print(f"Filesystem: {usage['filesystem']}")
print(f"Size: {usage['size']}")
print(f"Used: {usage['used']}")
print(f"Available: {usage['available']}")
print(f"Use%: {usage['used_percent']}")
print(f"Mounted on: {usage['mounted_on']}")
Parameters:
  • path (str, required) - Path to check (file or directory)
Returns: dict - Disk usage information Dict keys:
  • filesystem (str) - Filesystem device
  • size (int) - Total size in bytes
  • used (int) - Used space in bytes
  • available (int) - Available space in bytes
  • used_percent (int) - Percentage used
  • mounted_on (str) - Mount point

Usage Examples

Check File Exists Before Creating

from pyinfra import host
from pyinfra.facts.files import File
from pyinfra.operations import files

config_file = host.get_fact(File, path="/etc/myapp/config.ini")

if not config_file:
    files.put(
        name="Upload config",
        src="config.ini",
        dest="/etc/myapp/config.ini",
    )
else:
    host.noop("Config file already exists")

Check File Permissions

from pyinfra.facts.files import File
from pyinfra.operations import files

file_info = host.get_fact(File, path="/etc/app/secret.key")

if file_info and file_info["mode"] != 600:
    files.file(
        name="Fix secret.key permissions",
        path="/etc/app/secret.key",
        mode="600",
    )

Find and Process Config Files

from pyinfra.facts.files import FindFiles, File
from pyinfra.operations import files

# Find all config files
config_files = host.get_fact(
    FindFiles,
    path="/etc/nginx/sites-enabled",
    pattern="*.conf",
)

# Check each one
for config_path in config_files:
    file_info = host.get_fact(File, path=config_path)
    
    if file_info["user"] != "www-data":
        files.file(
            name=f"Fix owner of {config_path}",
            path=config_path,
            user="www-data",
            group="www-data",
        )

Search Config Files

from pyinfra.facts.files import FindInFile
from pyinfra.operations import files

# Check if debug mode is enabled
matches = host.get_fact(
    FindInFile,
    path="/etc/myapp/config.ini",
    pattern="^debug=true",
)

if matches:
    # Disable debug mode
    files.line(
        name="Disable debug mode",
        path="/etc/myapp/config.ini",
        line="debug=true",
        replace="debug=false",
    )

Check Disk Space

from pyinfra.facts.files import DiskUsage

usage = host.get_fact(DiskUsage, path="/var/log")

if usage["used_percent"] > 80:
    print(f"⚠️  Warning: /var/log is {usage['used_percent']}% full")
    # Maybe clean up old logs

Verify File Hash

from pyinfra.facts.files import Sha256File
from pyinfra.operations import files

expected_hash = "abc123def456..."
actual_hash = host.get_fact(Sha256File, path="/opt/app/binary")

if actual_hash != expected_hash:
    files.download(
        name="Download correct binary",
        src="https://example.com/app/binary",
        dest="/opt/app/binary",
    )

List Directory Contents

from pyinfra.facts.files import Directory

files = host.get_fact(Directory, path="/etc/nginx/sites-enabled")

if files:
    print(f"Found {len(files)} enabled sites:")
    for filename in files:
        print(f"  - {filename}")
else:
    print("Directory doesn't exist or is empty")

Complete Example

Here’s a comprehensive example using file facts:
from pyinfra import host
from pyinfra.facts.files import (
    File,
    Directory,
    FindInFile,
    DiskUsage,
    Sha256File,
)
from pyinfra.operations import files

# Check if application directory exists
app_dir = host.get_fact(File, path="/opt/myapp")

if not app_dir:
    files.directory(
        name="Create app directory",
        path="/opt/myapp",
        user="myapp",
        group="myapp",
        mode="755",
    )
elif app_dir["type"] != "directory":
    print("⚠️  Error: /opt/myapp exists but is not a directory")
    exit(1)

# Check disk space
usage = host.get_fact(DiskUsage, path="/opt")
if usage["used_percent"] > 90:
    print(f"⚠️  Critical: /opt is {usage['used_percent']}% full")
    exit(1)

# Verify application binary
expected_hash = "abc123..."
actual_hash = host.get_fact(Sha256File, path="/opt/myapp/bin/myapp")

if actual_hash != expected_hash:
    print("Updating application binary")
    files.put(
        name="Upload new binary",
        src="dist/myapp",
        dest="/opt/myapp/bin/myapp",
        mode="755",
    )

# Check configuration
config_file = host.get_fact(File, path="/etc/myapp/config.ini")

if not config_file:
    files.template(
        name="Create config",
        src="templates/config.ini.j2",
        dest="/etc/myapp/config.ini",
        mode="640",
        user="myapp",
        group="myapp",
    )
else:
    # Verify config permissions
    if config_file["mode"] != 640:
        files.file(
            name="Fix config permissions",
            path="/etc/myapp/config.ini",
            mode="640",
        )
    
    # Check for insecure settings
    debug_enabled = host.get_fact(
        FindInFile,
        path="/etc/myapp/config.ini",
        pattern="^debug=true",
    )
    
    if debug_enabled:
        print("⚠️  Warning: Debug mode is enabled in production")

# List log files
log_files = host.get_fact(Directory, path="/var/log/myapp")

if log_files:
    print(f"Found {len(log_files)} log files")
    
    # Check each log file size
    for log_file in log_files:
        log_path = f"/var/log/myapp/{log_file}"
        log_info = host.get_fact(File, path=log_path)
        
        # Warn about large log files
        if log_info and log_info["size"] > 100 * 1024 * 1024:  # 100 MB
            print(f"⚠️  Large log file: {log_file} ({log_info['size'] // 1024 // 1024} MB)")

print("✓ Application deployment verified")

Source Reference

Location: src/pyinfra/facts/files.py

Key Facts

  • File - Get file information (line 138+)
  • Directory - List directory contents
  • Link - Get symlink target
  • FindInFile - Search file contents
  • FindFiles - Find files by pattern
  • Sha256File - Get file hash
  • DiskUsage - Get disk usage

Build docs developers (and LLMs) love