os

package
v0.2.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 12 Imported by: 0

README

os

import "github.com/gechr/x/os"

Package os provides OS helpers: file probes, safe writes, copy, and line I/O.

Index

func AtomicWrite

func AtomicWrite(path string, data []byte, perm os.FileMode) error

AtomicWrite writes data to path via a temp-file-and-rename in the same directory. The temp file is removed on any failure.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "config.txt")
if err := xos.AtomicWrite(path, []byte("hello\n"), 0o600); err != nil {
    fmt.Println(err)
    return
}

data, _ := os.ReadFile(path)
fmt.Printf("%s", data)

Output:

hello

func CopyFile

func CopyFile(src, dst string) error

CopyFile copies src to dst, preserving src's mode bits. dst is fsynced before close. When src and dst are the same file (including via hard link) CopyFile is a no-op.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

src := filepath.Join(dir, "src.txt")
dst := filepath.Join(dir, "dst.txt")
_ = os.WriteFile(src, []byte("hello\n"), 0o600)

if err := xos.CopyFile(src, dst); err != nil {
    fmt.Println(err)
    return
}

data, _ := os.ReadFile(dst)
fmt.Printf("%s", data)

Output:

hello

func EnsureDir

func EnsureDir(dir string, perm os.FileMode) error

EnsureDir creates dir and any missing parents, and guarantees dir itself has mode perm even if it already existed with a different mode or the umask interfered at creation time. Pre-existing parents are left untouched.

Example

EnsureDir creates missing parent directories, like mkdir -p.

dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

nested := filepath.Join(dir, "a", "b", "c")
if err := xos.EnsureDir(nested, 0o755); err != nil {
    fmt.Println(err)
    return
}

isDir, _ := xos.IsDir(nested)
fmt.Println(isDir)

Output:

true

func EnsureFile

func EnsureFile(path string, perm os.FileMode) error

EnsureFile creates path as an empty file with mode perm if it does not exist, creating any missing parent directories. An existing file's contents, mode, and timestamps are left untouched.

Example

EnsureFile creates the file and any missing parent directories.

dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "a", "b", "config.txt")
if err := xos.EnsureFile(path, 0o600); err != nil {
    fmt.Println(err)
    return
}

isFile, _ := xos.IsFile(path)
fmt.Println(isFile)

Output:

true

func Exists

func Exists(path string) (bool, error)

Exists reports whether path exists.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "file.txt")
_ = os.WriteFile(path, []byte("hello"), 0o600)

exists, _ := xos.Exists(path)
missing, _ := xos.Exists(filepath.Join(dir, "missing.txt"))
fmt.Println(exists)
fmt.Println(missing)

Output:

true
false

func IsDir

func IsDir(path string) (bool, error)

IsDir reports whether path is a directory.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "file.txt")
_ = os.WriteFile(path, []byte("hello"), 0o600)

isDir, _ := xos.IsDir(dir)
notDir, _ := xos.IsDir(path)
fmt.Println(isDir)
fmt.Println(notDir)

Output:

true
false

func IsExecutable

func IsExecutable(path string) (bool, error)

IsExecutable reports whether path, with every symlink resolved, is a regular file that the current process can run as a binary. It answers the practical question rather than merely inspecting the permission bits: on Unix via access(2) with X_OK (so the owner/group/other bit that actually applies to this process is used), and on Windows via the resolved file's extension appearing in %PATHEXT% (Windows has no execute bit). A non-existent path reports false; a directory is traversable, not runnable, so it also reports false.

func IsFile

func IsFile(path string) (bool, error)

IsFile reports whether path is a regular file.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "file.txt")
_ = os.WriteFile(path, []byte("hello"), 0o600)

file, _ := xos.IsFile(path)
notFile, _ := xos.IsFile(dir)
fmt.Println(file)
fmt.Println(notFile)

Output:

true
false

func IsSymlink(path string) (bool, error)

IsSymlink reports whether path is a symbolic link.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "file.txt")
_ = os.WriteFile(path, []byte("hello"), 0o600)
link := filepath.Join(dir, "link.txt")
_ = os.Symlink(path, link)

isLink, _ := xos.IsSymlink(link)
notLink, _ := xos.IsSymlink(path)
fmt.Println(isLink)
fmt.Println(notLink)

Output:

true
false

func IsWritableDir

func IsWritableDir(dir string) bool

IsWritableDir reports whether dir exists and the current process can create files in it. Uses a probe file rather than permission-bit inspection so that ACLs and immutable mounts are handled correctly.

Example

A missing path is not a writable directory.

dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

fmt.Println(xos.IsWritableDir(dir))
fmt.Println(xos.IsWritableDir(filepath.Join(dir, "missing")))

Output:

true
false

func ReadLines

func ReadLines(path string) ([]string, error)

ReadLines reads path and returns its non-empty, trimmed lines.

Example

ReadLines drops blank lines and trims surrounding whitespace.

dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "lines.txt")
_ = os.WriteFile(path, []byte("  alpha  \n\n\tbeta\n\ngamma\n"), 0o600)

lines, _ := xos.ReadLines(path)
for _, line := range lines {
    fmt.Println(line)
}

Output:

alpha
beta
gamma

func SameFile

func SameFile(a, b string) (bool, error)

SameFile reports whether a and b identify the same file. Missing leaf paths are compared after resolving their parent directories, and existing files are compared with os.SameFile to detect hard links.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "file.txt")
_ = os.WriteFile(path, []byte("hello"), 0o600)
link := filepath.Join(dir, "link.txt")
_ = os.Link(path, link)
other := filepath.Join(dir, "other.txt")
_ = os.WriteFile(other, []byte("hello"), 0o600)

same, _ := xos.SameFile(path, link)
different, _ := xos.SameFile(path, other)
fmt.Println(same)
fmt.Println(different)

Output:

true
false

func Trash

func Trash(path string) error

Trash asks the operating system to move path to its trash (or recycle bin) rather than removing it permanently like os.Remove, so it can typically be recovered. The path is resolved to an absolute path first, so a relative path trashes the intended file regardless of the working directory.

The mechanism is platform-specific: the system trash tool on macOS (so the Finder's "Put Back" works), the FreeDesktop.org trash specification on Linux and other Unix systems, and the shell file operation that targets the Recycle Bin on Windows. Recoverability is the OS's to honor, not a guarantee: an environment with the Recycle Bin disabled, for instance, may delete outright.

Where the platform cannot trash, it returns an error wrapping errors.ErrUnsupported, so a caller can detect the case and decide what to do (e.g. fall back to os.Remove). This covers a macOS older than 15 (which lacks the system trash tool) and a Unix file with no usable same-device trash.

func WriteLines

func WriteLines(path string, lines []string, perm os.FileMode) error

WriteLines atomically writes lines to path, one per line, with a trailing newline.

Example
dir, _ := os.MkdirTemp("", "example")
defer func() { _ = os.RemoveAll(dir) }()

path := filepath.Join(dir, "lines.txt")
if err := xos.WriteLines(path, []string{"alpha", "beta"}, 0o600); err != nil {
    fmt.Println(err)
    return
}

data, _ := os.ReadFile(path)
fmt.Printf("%q\n", data)

Output:

"alpha\nbeta\n"

Documentation

Overview

Package os provides OS helpers: file probes, safe writes, copy, and line I/O.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AtomicWrite

func AtomicWrite(path string, data []byte, perm os.FileMode) error

AtomicWrite writes `data` to `path` via a temp-file-and-rename in the same directory. The temp file is removed on any failure.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "config.txt")
	if err := xos.AtomicWrite(path, []byte("hello\n"), 0o600); err != nil {
		fmt.Println(err)
		return
	}

	data, _ := os.ReadFile(path)
	fmt.Printf("%s", data)
}
Output:
hello

func CopyFile

func CopyFile(src, dst string) error

CopyFile copies `src` to `dst`, preserving `src`'s mode bits. `dst` is fsynced before close. When `src` and `dst` are the same file (including via hard link) CopyFile is a no-op.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	src := filepath.Join(dir, "src.txt")
	dst := filepath.Join(dir, "dst.txt")
	_ = os.WriteFile(src, []byte("hello\n"), 0o600)

	if err := xos.CopyFile(src, dst); err != nil {
		fmt.Println(err)
		return
	}

	data, _ := os.ReadFile(dst)
	fmt.Printf("%s", data)
}
Output:
hello

func EnsureDir

func EnsureDir(dir string, perm os.FileMode) error

EnsureDir creates `dir` and any missing parents, and guarantees `dir` itself has mode `perm` even if it already existed with a different mode or the umask interfered at creation time. Pre-existing parents are left untouched.

Example

EnsureDir creates missing parent directories, like mkdir -p.

package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	nested := filepath.Join(dir, "a", "b", "c")
	if err := xos.EnsureDir(nested, 0o755); err != nil {
		fmt.Println(err)
		return
	}

	isDir, _ := xos.IsDir(nested)
	fmt.Println(isDir)
}
Output:
true

func EnsureFile

func EnsureFile(path string, perm os.FileMode) error

EnsureFile creates `path` as an empty file with mode `perm` if it does not exist, creating any missing parent directories. An existing file's contents, mode, and timestamps are left untouched.

Example

EnsureFile creates the file and any missing parent directories.

package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "a", "b", "config.txt")
	if err := xos.EnsureFile(path, 0o600); err != nil {
		fmt.Println(err)
		return
	}

	isFile, _ := xos.IsFile(path)
	fmt.Println(isFile)
}
Output:
true

func Exists

func Exists(path string) (bool, error)

Exists reports whether `path` exists.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "file.txt")
	_ = os.WriteFile(path, []byte("hello"), 0o600)

	exists, _ := xos.Exists(path)
	missing, _ := xos.Exists(filepath.Join(dir, "missing.txt"))
	fmt.Println(exists)
	fmt.Println(missing)
}
Output:
true
false

func IsDir

func IsDir(path string) (bool, error)

IsDir reports whether `path` is a directory.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "file.txt")
	_ = os.WriteFile(path, []byte("hello"), 0o600)

	isDir, _ := xos.IsDir(dir)
	notDir, _ := xos.IsDir(path)
	fmt.Println(isDir)
	fmt.Println(notDir)
}
Output:
true
false

func IsExecutable

func IsExecutable(path string) (bool, error)

IsExecutable reports whether `path`, with every symlink resolved, is a regular file that the current process can run as a binary. It answers the practical question rather than merely inspecting the permission bits: on Unix via `access(2)` with `X_OK` (so the owner/group/other bit that actually applies to this process is used), and on Windows via the resolved file's extension appearing in `%PATHEXT%` (Windows has no execute bit). A non-existent path reports false; a directory is traversable, not runnable, so it also reports false.

func IsFile

func IsFile(path string) (bool, error)

IsFile reports whether `path` is a regular file.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "file.txt")
	_ = os.WriteFile(path, []byte("hello"), 0o600)

	file, _ := xos.IsFile(path)
	notFile, _ := xos.IsFile(dir)
	fmt.Println(file)
	fmt.Println(notFile)
}
Output:
true
false
func IsSymlink(path string) (bool, error)

IsSymlink reports whether `path` is a symbolic link.

func IsWritableDir

func IsWritableDir(dir string) bool

IsWritableDir reports whether `dir` exists and the current process can create files in it. Uses a probe file rather than permission-bit inspection so that ACLs and immutable mounts are handled correctly.

Example

A missing path is not a writable directory.

package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	fmt.Println(xos.IsWritableDir(dir))
	fmt.Println(xos.IsWritableDir(filepath.Join(dir, "missing")))
}
Output:
true
false

func ReadLines

func ReadLines(path string) ([]string, error)

ReadLines reads `path` and returns its non-empty, trimmed lines.

Example

ReadLines drops blank lines and trims surrounding whitespace.

package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "lines.txt")
	_ = os.WriteFile(path, []byte("  alpha  \n\n\tbeta\n\ngamma\n"), 0o600)

	lines, _ := xos.ReadLines(path)
	for _, line := range lines {
		fmt.Println(line)
	}
}
Output:
alpha
beta
gamma

func SameFile

func SameFile(a, b string) (bool, error)

SameFile reports whether `a` and `b` identify the same file. Missing leaf paths are compared after resolving their parent directories, and existing files are compared with os.SameFile to detect hard links.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "file.txt")
	_ = os.WriteFile(path, []byte("hello"), 0o600)
	link := filepath.Join(dir, "link.txt")
	_ = os.Link(path, link)
	other := filepath.Join(dir, "other.txt")
	_ = os.WriteFile(other, []byte("hello"), 0o600)

	same, _ := xos.SameFile(path, link)
	different, _ := xos.SameFile(path, other)
	fmt.Println(same)
	fmt.Println(different)
}
Output:
true
false

func Trash

func Trash(path string) error

Trash asks the operating system to move `path` to its trash (or recycle bin) rather than removing it permanently like os.Remove, so it can typically be recovered. The `path` is resolved to an absolute path first, so a relative path trashes the intended file regardless of the working directory.

The mechanism is platform-specific: the system trash tool on macOS (so the Finder's "Put Back" works), the FreeDesktop.org trash specification on Linux and other Unix systems, and the shell file operation that targets the Recycle Bin on Windows. Recoverability is the OS's to honor, not a guarantee: an environment with the Recycle Bin disabled, for instance, may delete outright.

Where the platform cannot trash, it returns an error wrapping errors.ErrUnsupported, so a caller can detect the case and decide what to do (e.g. fall back to os.Remove). This covers a macOS older than 15 (which lacks the system trash tool) and a Unix file with no usable same-device trash.

func WriteLines

func WriteLines(path string, lines []string, perm os.FileMode) error

WriteLines atomically writes `lines` to `path`, one per line, with a trailing newline.

Example
package main

import (
	"fmt"
	"os"
	"path/filepath"

	xos "github.com/gechr/x/os"
)

func main() {
	dir, _ := os.MkdirTemp("", "example")
	defer func() { _ = os.RemoveAll(dir) }()

	path := filepath.Join(dir, "lines.txt")
	if err := xos.WriteLines(path, []string{"alpha", "beta"}, 0o600); err != nil {
		fmt.Println(err)
		return
	}

	data, _ := os.ReadFile(path)
	fmt.Printf("%q\n", data)
}
Output:
"alpha\nbeta\n"

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL