Loading pageā¦
Rust walkthroughs
Loading pageā¦
tempfile::tempdir_in and tempdir for custom temporary directory locations?tempfile::tempdir() creates temporary directories in the system's default temporary directory (/tmp on Unix, %TEMP% on Windows), while tempfile::tempdir_in() allows specifying a custom parent directory for temporary storage. The trade-offs span security, cleanup guarantees, disk space management, permissions, and containerized environments: default temporary directories benefit from OS-managed cleanup policies but may have limited space or restrictive permissions, while custom locations provide control over storage location and quotas but require manual consideration of cleanup semantics and cross-platform behavior. The choice depends on whether you need large temporary files that exceed /tmp capacity, want isolation from other processes, require specific filesystem features, or need predictable locations in containerized deployments.
use tempfile::tempdir;
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
// Creates a directory in system default temp location
let dir = tempdir()?;
println!("Temp directory: {:?}", dir.path());
// On Unix: /tmp/tmplOkJkL (random suffix)
// On Windows: C:\Users\...\AppData\Local\Temp\tmpABCDE
let file_path = dir.path().join("output.txt");
let mut file = File::create(&file_path)?;
file.write_all(b"Hello, temp!")?;
// Directory and contents deleted when `dir` goes out of scope
Ok(())
}tempdir() uses the system default location, which varies by platform.
use tempfile::tempdir_in;
use std::fs::File;
use std::io::Write;
fn main() -> std::io::Result<()> {
// Creates a directory in a custom location
let dir = tempdir_in("./my_temp")?;
println!("Temp directory: {:?}", dir.path());
// ./my_temp/tmpABCDE (inside specified directory)
let file_path = dir.path().join("data.txt");
let mut file = File::create(&file_path)?;
file.write_all(b"Custom location!")?;
// Still cleaned up automatically
Ok(())
}tempdir_in() creates the temp directory inside a custom parent path.
use tempfile::tempdir;
fn main() -> std::io::Result<()> {
// System default temp directory varies:
// Unix: Usually /tmp, respects TMPDIR env var
// Windows: %TEMP% or %TMP% environment variable
let dir = tempdir()?;
println!("Default temp location: {:?}", dir.path());
// The default location has characteristics:
// 1. OS may clean up old files periodically
// 2. May be a tmpfs (in-memory filesystem)
// 3. Usually world-writable (with sticky bit on Unix)
// 4. May have size limits
// Environment variable influence:
std::env::set_var("TMPDIR", "/custom/temp");
let dir2 = tempdir()?; // Now uses /custom/temp
println!("Custom env temp: {:?}", dir2.path());
Ok(())
}Default temp location is configurable via environment variables.
use tempfile::{tempdir, tempdir_in, Builder};
use std::path::Path;
fn main() -> std::io::Result<()> {
// Default /tmp security model:
// - World-writable directory
// - Sticky bit prevents deletion by non-owners
// - Still potentially observable by other users
let default_dir = tempdir()?;
println!("Default dir: {:?}", default_dir.path());
// Custom location can provide isolation:
// - Directory permissions controlled by parent
// - Not visible to users without access to parent
// Create in a restricted location
let custom_dir = tempdir_in("/home/user/private/.cache")?;
println!("Custom dir: {:?}", custom_dir.path());
// More secure with explicit permissions
let secure_dir = Builder::new()
.permissions(std::fs::Permissions::from_mode(0o700))
.tempdir_in("/home/user/private")?;
println!("Secure dir: {:?}", secure_dir.path());
Ok(())
}Custom locations can provide better isolation from other users.
use tempfile::{tempdir, tempdir_in};
use std::fs::File;
use std::io::Write;
fn write_large_tempfile(dir: &std::path::Path, size_mb: usize) -> std::io::Result<()> {
let file_path = dir.join("large_file.bin");
let mut file = File::create(&file_path)?;
let chunk = vec
![0u8; 1024 * 1024]; // 1MB
for _ in 0..size_mb {
file.write_all(&chunk)?;
}
Ok(())
}
fn main() -> std::io::Result<()> {
// Problem: /tmp might be small (tmpfs with limited RAM)
// Default /tmp could be only a few GB
// This might fail if /tmp is too small:
// let dir = tempdir()?;
// write_large_tempfile(dir.path(), 10_000)?; // 10GB might fail
// Solution: Use a partition with more space
let dir = tempdir_in("/data/temp")?;
println!("Using /data/temp for large files");
write_large_tempfile(dir.path(), 100)?; // 100MB test
// Custom location on larger partition
Ok(())
}Custom locations help when /tmp has insufficient space.
use tempfile::{tempdir, tempdir_in};
fn main() -> std::io::Result<()> {
// In containers, default /tmp may be:
// 1. In the container's writable layer (slow)
// 2. Mounted as emptyDir (Kubernetes)
// 3. A volume mount
// Docker example: volume mounted at /app/data
// Default tempdir would use container's /tmp
let default_dir = tempdir()?;
println!("Container default: {:?}", default_dir.path());
// Better: use mounted volume for persistence/performance
let volume_dir = tempdir_in("/app/data/temp")?;
println!("Volume temp: {:?}", volume_dir.path());
// Kubernetes: use emptyDir mount point
let k8s_dir = tempdir_in("/tmp/emptydir")?;
println!("K8s temp: {:?}", k8s_dir.path());
Ok(())
}Containers often benefit from explicit temp locations matching volume mounts.
use tempfile::{tempdir, tempdir_in, TempDir};
use std::fs;
fn main() -> std::io::Result<()> {
// Both tempdir() and tempdir_in() return TempDir
// TempDir::drop deletes the directory and contents
let dir = tempdir()?;
let path = dir.path().to_path_buf();
// Create some files
fs::create_dir(dir.path().join("subdir"))?;
fs::write(dir.path().join("file.txt"), b"content")?;
// Check it exists
assert!(path.exists());
// Into_path() prevents cleanup
let dir2 = tempdir_in(".")?;
let kept_path = dir2.into_path(); // Consumes TempDir
// kept_path still exists after this function
// We own it now, must clean up manually
println!("Kept path: {:?}", kept_path);
// Cleanup happens automatically unless into_path()
Ok(())
}Both provide automatic cleanup; into_path() preserves the directory.
use tempfile::{tempdir, tempdir_in, Builder};
use std::os::unix::fs::PermissionsExt;
fn main() -> std::io::Result<()> {
// Default tempdir uses system umask
let default = tempdir()?;
// Custom location inherits parent permissions
// Plus umask modification
// Fine-grained control with Builder
let restricted = Builder::new()
.permissions(std::fs::Permissions::from_mode(0o700))
.tempdir_in("/home/user")?;
// Only owner can access
println!("Restricted temp: {:?}", restricted.path());
// Group-accessible temp
let shared = Builder::new()
.permissions(std::fs::Permissions::from_mode(0o750))
.tempdir_in("/home/user/shared")?;
println!("Shared temp: {:?}", shared.path());
Ok(())
}Builder provides fine-grained permission control for custom locations.
use tempfile::{tempdir, tempdir_in, Builder};
use std::path::PathBuf;
fn get_temp_base() -> PathBuf {
#[cfg(unix)]
{
PathBuf::from("/var/cache/myapp")
}
#[cfg(windows)]
{
// Windows: AppData/Local/myapp/cache
dirs::cache_dir()
.unwrap_or_else(|| std::env::temp_dir())
.join("myapp")
}
}
fn main() -> std::io::Result<()> {
// Default tempdir is platform-aware
let default = tempdir()?;
println!("Default temp: {:?}", default.path());
// Custom location needs platform consideration
let base = get_temp_base();
std::fs::create_dir_all(&base)?;
let custom = tempdir_in(&base)?;
println!("Custom temp: {:?}", custom.path());
// Builder provides cross-platform configuration
let dir = Builder::new()
.prefix("myapp_")
.suffix("_temp")
.tempdir_in(&base)?;
println!("Named temp: {:?}", dir.path());
Ok(())
}Custom locations require platform-specific path handling.
use tempfile::{tempdir, tempdir_in, Builder};
fn main() -> std::io::Result<()> {
// Default: random name with "tmp" prefix
let default = tempdir()?;
println!("Default name: {:?}", default.path().file_name());
// tempdir_in: still random name, custom parent
let custom_parent = tempdir_in("./scratch")?;
println!("Custom parent: {:?}", custom_parent.path());
// Builder: control prefix and suffix
let named = Builder::new()
.prefix("session_")
.suffix("_cache")
.tempdir()?; // Or tempdir_in() for custom location
println!("Named temp: {:?}", named.path());
// session_ABCD123_cache
// Useful for:
// - Identifiable temp directories in logs
// - Debugging which process created which temp
// - Sorting/grouping temp directories
Ok(())
}Builder allows custom prefixes and suffixes for both functions.
use tempfile::{tempdir, tempdir_in};
use std::fs::File;
use std::io::Write;
use std::time::Instant;
fn benchmark_tempdir<P: AsRef<std::path::Path>>(
path: P,
iterations: usize,
) -> std::io::Result<std::time::Duration> {
let start = Instant::now();
for _ in 0..iterations {
let dir = tempdir_in(&path)?;
let file_path = dir.path().join("test.txt");
let mut file = File::create(&file_path)?;
file.write_all(b"test content")?;
// Drop: cleanup happens here
}
Ok(start.elapsed())
}
fn main() -> std::io::Result<()> {
// Different filesystems have different performance
let tmpfs_time = benchmark_tempdir("/tmp", 100)?;
println!("tmpfs tempdir: {:?}", tmpfs_time);
// SSD vs HDD vs Network mount
// /tmp might be tmpfs (fast, in-memory)
// /home/user/temp might be SSD or HDD
// tmpfs: very fast for small files, limited by RAM
// SSD: good for many small temp files
// HDD: slower, better for large sequential writes
// Network: high latency, avoid for temp files
Ok(())
}Location choice affects performance based on underlying filesystem.
use tempfile::{tempdir, tempdir_in, Builder};
fn main() -> std::io::Result<()> {
// Application-wide temp in default location
// May conflict with other apps or user temp files
let app_dir = tempdir()?;
println!("App temp: {:?}", app_dir.path());
// Isolated temp directory for specific operation
let compile_dir = tempdir_in("./build")?;
println!("Compile temp: {:?}", compile_dir.path());
// Different isolation levels:
// 1. Application-specific
let app_specific = Builder::new()
.prefix("myapp_")
.tempdir()?; // Still in /tmp but prefixed
// 2. Project-specific
let project_temp = tempdir_in("./project/.cache")?;
// 3. User-specific (already in user home)
let user_temp = tempdir_in(dirs::cache_dir().unwrap())?;
// 4. Operation-specific isolation
let isolated = Builder::new()
.permissions(std::fs::Permissions::from_mode(0o700))
.tempdir_in("/var/run/user/1000")?;
Ok(())
}Custom locations enable different isolation strategies.
use tempfile::{tempdir, tempdir_in, Builder};
use std::path::Path;
fn main() {
// tempdir() errors on system problems
match tempdir() {
Ok(dir) => println!("Created: {:?}", dir.path()),
Err(e) => eprintln!("Failed to create tempdir: {}", e),
}
// tempdir_in() errors if parent doesn't exist
match tempdir_in("/nonexistent/path") {
Ok(dir) => println!("Created: {:?}", dir.path()),
Err(e) => {
// Parent directory must exist
eprintln!("Failed: {} (parent may not exist)", e);
}
}
// Robust approach: create parent first
fn ensure_tempdir_in<P: AsRef<Path>>(path: P) -> std::io::Result<tempfile::TempDir> {
std::fs::create_dir_all(path.as_ref())?;
tempdir_in(path)
}
match ensure_tempdir_in("./data/temp") {
Ok(dir) => println!("Ensured: {:?}", dir.path()),
Err(e) => eprintln!("Still failed: {}", e),
}
}tempdir_in requires the parent directory to exist; tempdir() doesn't.
use tempfile::{tempdir, tempdir_in, Builder};
fn main() -> std::io::Result<()> {
// tempdir() - default location
let default = tempdir()?;
// tempdir_in() - custom location
let custom = tempdir_in("./scratch")?;
// Both support Builder for configuration
let configured = Builder::new()
.prefix("app_")
.suffix("_tmp")
.permissions(std::fs::Permissions::from_mode(0o700))
.tempdir_in("./workspace")?;
// All return TempDir with automatic cleanup
println!("Default: {:?}", default.path());
println!("Custom: {:?}", custom.path());
println!("Configured: {:?}", configured.path());
// Cleanup on drop for all
Ok(())
}Both functions return TempDir; difference is the parent directory location.
Function comparison:
| Aspect | tempdir() | tempdir_in() |
|--------|-------------|----------------|
| Parent directory | System default | Custom path |
| Parent must exist | N/A (system ensures) | Yes |
| Disk space | Limited by /tmp | Limited by target filesystem |
| Permissions | System default | Inherits from parent |
| Isolation | Shared with other processes | Can be isolated |
| Cross-platform | Automatic | Manual handling needed |
When to use tempdir():
| Scenario | Reason | |----------|--------| | Small temporary files | Default space sufficient | | Cross-platform code | System handles location | | Quick prototypes | No configuration needed | | Short-lived processes | Standard cleanup policies |
When to use tempdir_in():
| Scenario | Reason |
|----------|--------|
| Large temp files | Need more space than /tmp |
| Container volumes | Match mounted volumes |
| Security isolation | Restricted parent permissions |
| Application-specific cache | Project-local temp directories |
| Performance | Choose faster filesystem |
| Persistence testing | Control when cleanup happens |
Key insight: The trade-off between tempdir() and tempdir_in() centers on control versus convenience. tempdir() provides maximum convenienceāthe system provides a known-good temporary directory with OS-managed cleanup policies, appropriate permissions, and cross-platform behavior. This works well for small, short-lived temporary data that fits within typical /tmp constraints. tempdir_in() trades this convenience for control: you specify exactly where temporary files live, enabling storage of large files on partitions with sufficient space, isolation from system temporary directories, alignment with container volume mounts, and custom permission models. The parent directory must exist (unlike tempdir() which relies on the system), requiring explicit creation or error handling. In practice, use tempdir() for general-purpose temporary storage unless you have specific requirements around disk space, security, performance, or containerization that necessitate a custom location. Use tempdir_in() when you need predictable storage locations, isolation from other processes' temporary files, or alignment with application-specific directory structures.