Skip to main content
The device module provides functions to inspect, classify, and manage device files including block devices, character devices, and special system devices.

Device inspection

Functions to check device properties and status.
Check if path is a character device.
device.sh:10
device::is_device() {
    [[ -c "$1" ]]
}
Check if path is a block device.
device.sh:15
device::is_block() {
    [[ -b "$1" ]]
}
Check if device is writable.
device.sh:20
device::is_writeable() {
    [[ -w "$1" ]]
}
Check if device is readable.
device.sh:25
device::is_readable() {
    [[ -r "$1" ]]
}
Check if device exists (block or character).
device.sh:30
device::exists() {
    [[ -b "$1" || -c "$1" ]]
}
Check if device has open file handles via lsof.
device.sh:35
device::has_processes() {
    runtime::has_command lsof || return 1
    lsof -t "$1" >/dev/null 2>&1
}
Check if device is occupied via /proc (no lsof needed).
device.sh:41
device::is_occupied() {
    find /proc/[0-9]*/fd -lname "*${1#/dev/}" 2>/dev/null | head -1 | grep -q .
}
Check if a block device is mounted.
device.sh:46
device::is_mounted() {
    grep -q "^$1 " /proc/mounts 2>/dev/null \
        || grep -q " $1 " /proc/mounts 2>/dev/null
}
Usage:
if device::is_mounted /dev/sda1; then
  echo "Device is mounted"
fi
Check if device is a loop device.
device.sh:52
device::is_loop() {
    [[ "$1" == /dev/loop* ]]
}
Check if device is a RAM disk.
device.sh:57
device::is_ram() {
    [[ "$1" == /dev/ram* || "$1" == /dev/zram* ]]
}
Check if device is a virtual/pseudo device.
device.sh:62
device::is_virtual() {
    case "$1" in
        /dev/null | /dev/zero | /dev/full | /dev/random | \
        /dev/urandom | /dev/stdin | /dev/stdout | /dev/stderr | \
        /dev/fd/* | /dev/ptmx | /dev/tty*)
            return 0 ;;
        *)
            return 1 ;;
    esac
}
Detects:
  • /dev/null, /dev/zero, /dev/full
  • /dev/random, /dev/urandom
  • /dev/stdin, /dev/stdout, /dev/stderr
  • /dev/fd/*, /dev/ptmx, /dev/tty*

Device classification

Functions to identify device types and properties.
Returns the type of a device as a string.
device.sh:80
device::type() {
    local dev="$1"
    local base="${dev##*/}"

    # Virtual/pseudo devices first
    device::is_virtual "$dev" && echo "virtual"   && return
    device::is_loop "$dev"    && echo "loop"      && return
    device::is_ram "$dev"     && echo "ram"       && return

    # TTY / PTY
    [[ "$dev" == /dev/tty*  ]] && echo "tty" && return
    [[ "$dev" == /dev/pts/* ]] && echo "pty" && return

    # NVMe
    [[ "$base" =~ ^nvme[0-9]+n[0-9]+p[0-9]+$ ]] && echo "partition" && return
    [[ "$base" =~ ^nvme[0-9]+n[0-9]+$        ]] && echo "nvme"      && return

    # SD/SAS/SATA partitions vs disks
    [[ "$base" =~ ^sd[a-z]+[0-9]+$  ]] && echo "partition" && return
    [[ "$base" =~ ^sd[a-z]+$        ]] && echo "disk"      && return

    # MMC / eMMC
    [[ "$base" =~ ^mmcblk[0-9]+p[0-9]+$ ]] && echo "partition" && return
    [[ "$base" =~ ^mmcblk[0-9]+$        ]] && echo "disk"      && return

    # IDE (legacy)
    [[ "$base" =~ ^hd[a-z]+[0-9]+$ ]] && echo "partition" && return
    [[ "$base" =~ ^hd[a-z]+$       ]] && echo "disk"      && return

    # Optical
    [[ "$base" =~ ^sr[0-9]+$  ]] && echo "optical" && return
    [[ "$base" =~ ^cd[a-z]+$  ]] && echo "optical" && return

    # USB block devices (often shows as sdX — covered above, but flag specific paths)
    [[ "$dev" == /dev/bus/usb/* ]] && echo "usb" && return

    # Generic character vs block fallback
    device::is_block "$dev"  && echo "block" && return
    device::is_device "$dev" && echo "char"  && return

    echo "unknown"
}
Possible returns:
  • virtual - Virtual/pseudo device
  • loop - Loop device
  • ram - RAM disk
  • tty - Terminal device
  • pty - Pseudo-terminal
  • partition - Disk partition
  • nvme - NVMe device
  • disk - Physical disk
  • optical - CD/DVD drive
  • usb - USB device
  • block - Generic block device
  • char - Generic character device
  • unknown - Unknown type
Returns the major:minor device number.
device.sh:124
device::number() {
    local dev="$1"
    if runtime::has_command stat; then
        case "$(runtime::os)" in
        linux|wsl|cygwin|mingw)
            stat -c '%t:%T' "$dev" 2>/dev/null | \
                awk -F: '{ printf "%d:%d\n", strtonum("0x"$1), strtonum("0x"$2) }'
            ;;
        darwin)
            stat -f '%Hr:%Lr' "$dev" 2>/dev/null
            ;;
        *)
            echo "unknown"
            ;;
        esac
    else
        echo "unknown"
    fi
}
Usage:
device::number /dev/sda1  # 8:1
Returns the filesystem on a block device (if mounted or detectable).
device.sh:146
device::filesystem() {
    local dev="$1"
    case "$(runtime::os)" in
    linux|wsl)
        if runtime::has_command blkid; then
            blkid -o value -s TYPE "$dev" 2>/dev/null || echo "unknown"
        else
            echo "unknown"
        fi
        ;;
    darwin)
        diskutil info "$dev" 2>/dev/null \
            | awk -F': +' '/Type \(Bundle\)/ { print $2 }' || echo "unknown"
        ;;
    *)
        echo "unknown"
        ;;
    esac
}
Usage:
device::filesystem /dev/sda1  # ext4
Returns the size of a block device in bytes.
device.sh:167
device::size_bytes() {
    local dev="$1"
    case "$(runtime::os)" in
    linux|wsl)
        if [[ -r "/sys/block/${dev##*/}/size" ]]; then
            # /sys/block reports 512-byte sectors
            echo $(( $(cat "/sys/block/${dev##*/}/size") * 512 ))
        elif runtime::has_command blockdev; then
            blockdev --getsize64 "$dev" 2>/dev/null || echo "unknown"
        else
            echo "unknown"
        fi
        ;;
    darwin)
        diskutil info "$dev" 2>/dev/null \
            | awk -F': +' '/Disk Size/ { match($2, /[0-9]+/, a); print a[0] }' \
            || echo "unknown"
        ;;
    *)
        echo "unknown"
        ;;
    esac
}
Returns the size of a block device in MB.
device.sh:192
device::size_mb() {
    local bytes
    bytes=$(device::size_bytes "$1")
    [[ "$bytes" == "unknown" ]] && echo "unknown" && return
    echo $(( bytes / 1024 / 1024 ))
}
Returns the mount point of a block device (empty if not mounted).
device.sh:200
device::mount_point() {
    local dev="$1"
    case "$(runtime::os)" in
    linux|wsl)
        grep "^$dev " /proc/mounts 2>/dev/null | awk '{print $2}' | head -1
        ;;
    darwin)
        diskutil info "$dev" 2>/dev/null \
            | awk -F': +' '/Mount Point/ { print $2 }'
        ;;
    *)
        echo ""
        ;;
    esac
}
Usage:
mount_point=$(device::mount_point /dev/sda1)
echo "Mounted at: $mount_point"

Device listing

Functions to enumerate devices on the system.
List all block devices.
device.sh:221
device::list::block() {
    case "$(runtime::os)" in
    linux|wsl)
        lsblk -dno NAME 2>/dev/null | sed 's/^/\/dev\//' | grep -v loop
        ;;
    darwin)
        diskutil list 2>/dev/null | awk '/^\/dev\// { print $1 }'
        ;;
    *)
        echo "unknown"
        ;;
    esac
}
List all character devices.
device.sh:236
device::list::char() {
    find /dev -maxdepth 1 -type c 2>/dev/null | sort
}
List all TTY devices.
device.sh:241
device::list::tty() {
    find /dev -maxdepth 1 -name 'tty*' -type c 2>/dev/null | sort
}
List all loop devices.
device.sh:246
device::list::loop() {
    find /dev -maxdepth 1 -name 'loop*' -type b 2>/dev/null | sort
}
List mounted devices with their mount points.
device.sh:251
device::list::mounted() {
    case "$(runtime::os)" in
    linux|wsl)
        grep '^/dev/' /proc/mounts 2>/dev/null | awk '{print $1, $2}'
        ;;
    darwin)
        mount 2>/dev/null | awk '/^\/dev\// { print $1, $3 }'
        ;;
    *)
        echo "unknown"
        ;;
    esac
}
Usage:
device::list::mounted
# Output:
# /dev/sda1 /
# /dev/sda2 /home

Special devices

Functions for working with special system devices.
Write n bytes of zeros to a device or file (wraps /dev/zero).
device.sh:272
device::zero() {
    local target="$1" bytes="${2:-16}"
    if [[ -n "$bytes" ]]; then
        dd if=/dev/zero of="$target" bs=1 count="$bytes" 2>/dev/null
    else
        dd if=/dev/zero of="$target" 2>/dev/null
    fi
}
Warning: This is destructive — use with care.Usage:
# Write 1024 bytes of zeros
device::zero /tmp/test 1024
Read n random bytes from /dev/urandom.
device.sh:283
device::random() {
    local bytes="${1:-16}"
    dd if=/dev/urandom bs=1 count="$bytes" 2>/dev/null | od -An -tx1 | tr -d ' \n'
    echo
}
Usage:
token=$(device::random 32)
echo "Random token: $token"
Check if /dev/null is functional (sanity check).
device.sh:290
device::null_ok() {
    echo "" > /dev/null 2>&1
}

Build docs developers (and LLMs) love