Skip to content
Back to skills

702 Pure Bash Bible Files 04521d3d

CSecurity

Reference: [pure-bash-bible](https://github.com/dylanaraps/pure-bash-bible) Pure bash alternatives to file processing commands like cat, head, tail, wc, basename, and dirname. **Note:** Bash versions < 4.4 have issues handling binary data.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 11, 2026
documentationbashnodegit

Security analysis

C68/100
  • criticalAccesses sensitive system or user directories
  • highPerforms destructive filesystem operations
  • criticalModifies startup scripts or system services for persistence

Pro shows the line behind each finding and how to fix it

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 702-pure-bash-bible-files_04521d3d --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 702 Pure Bash Bible Files 04521d3d?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 702 Pure Bash Bible Files 04521d3d
[![Security: C — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-702-pure-bash-bible-files-04521d3d/badge)](https://www.skillsdirectory.com/skills/tools-only-702-pure-bash-bible-files-04521d3d)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
# Pure Bash Bible - File Operations

Reference: [pure-bash-bible](https://github.com/dylanaraps/pure-bash-bible)

Pure bash alternatives to file processing commands like cat, head, tail, wc, basename, and dirname.

**Note:** Bash versions < 4.4 have issues handling binary data.

## Read File to String

Alternative to `cat`:

```bash
file_data="$(<"file")"

# With error checking
if [[ -r "${file}" ]]; then
    content="$(<"${file}")"
fi
```

## Read File to Array (by line)

```bash
# Bash <4 (discarding empty lines)
IFS=$'\n' read -d "" -ra file_data < "file"

# Bash <4 (preserving empty lines)
while read -r line; do
    file_data+=("$line")
done < "file"

# Bash 4+
mapfile -t file_data < "file"
```

## Get First N Lines (head alternative)

Requires Bash 4+:

```bash
head() {
    mapfile -tn "$1" line < "$2"
    printf '%s\n' "${line[@]}"
}

# Usage
head 2 ~/.bashrc       # First 2 lines
head 10 /etc/passwd    # First 10 lines
```

## Get Last N Lines (tail alternative)

Requires Bash 4+:

```bash
tail() {
    mapfile -tn 0 line < "$2"
    printf '%s\n' "${line[@]: -$1}"
}

# Usage
tail 2 ~/.bashrc       # Last 2 lines
tail 10 /var/log/syslog
```

## Count Lines in File (wc -l alternative)

```bash
# Bash 4+ (mapfile)
lines() {
    mapfile -tn 0 lines < "$1"
    printf '%s\n' "${#lines[@]}"
}

# Bash 3 (slower for large files)
lines_loop() {
    local count=0
    while IFS= read -r _; do
        ((count++))
    done < "$1"
    printf '%s\n' "$count"
}

# Usage
lines ~/.bashrc  # Output: number of lines
```

## Count Files in Directory

```bash
count() {
    printf '%s\n' "$#"
}

# Usage
count ~/Downloads/*      # Count all files
count ~/Downloads/*/     # Count directories only
count ~/Pictures/*.jpg   # Count specific type
```

## Create Empty File (touch alternative)

```bash
# Shortest
>file

# Alternatives
:>file
echo -n >file
printf '' >file
```

## Extract Lines Between Markers

````bash
extract() {
    # Usage: extract file "opening marker" "closing marker"
    while IFS=$'\n' read -r line; do
        [[ $extract && $line != "$3" ]] &&
            printf '%s\n' "$line"
        [[ $line == "$2" ]] && extract=1
        [[ $line == "$3" ]] && extract=
    done < "$1"
}

# Usage: Extract code blocks from markdown
extract README.md '```bash' '```'
````

## Get Directory Name (dirname alternative)

```bash
dirname() {
    local tmp=${1:-.}
    [[ $tmp != *[!/]* ]] && { printf '/\n'; return; }
    tmp=${tmp%%"${tmp##*[!/]}"}
    [[ $tmp != */* ]] && { printf '.\n'; return; }
    tmp=${tmp%/*}
    tmp=${tmp%%"${tmp##*[!/]}"}
    printf '%s\n' "${tmp:-/}"
}

# Usage
dirname ~/Pictures/Wallpapers/1.jpg  # /home/user/Pictures/Wallpapers
dirname ~/Pictures/Downloads/        # /home/user/Pictures
```

## Get Basename (basename alternative)

```bash
basename() {
    local tmp
    tmp=${1%"${1##*[!/]}"}
    tmp=${tmp##*/}
    tmp=${tmp%"${2/"$tmp"}"}
    printf '%s\n' "${tmp:-/}"
}

# Usage
basename ~/Pictures/Wallpapers/1.jpg       # 1.jpg
basename ~/Pictures/Wallpapers/1.jpg .jpg  # 1
basename ~/Pictures/Downloads/             # Downloads
```

## File Iteration Patterns

```bash
# All files (greedy)
for file in *; do
    printf '%s\n' "$file"
done

# Specific extension
for file in ~/Pictures/*.png; do
    printf '%s\n' "$file"
done

# Directories only
for dir in ~/Downloads/*/; do
    printf '%s\n' "$dir"
done

# Multiple paths with brace expansion
for file in /path/to/parentdir/{file1,file2,subdir/file3}; do
    printf '%s\n' "$file"
done

# Recursive (requires globstar)
shopt -s globstar
for file in ~/Pictures/**/*; do
    printf '%s\n' "$file"
done
shopt -u globstar
```

## Loop Over File Contents

```bash
# Standard line-by-line
while read -r line; do
    printf '%s\n' "$line"
done < "file"

# With IFS preservation for leading/trailing whitespace
while IFS= read -r line; do
    printf '%s\n' "$line"
done < "file"

# Handle files without trailing newline
while IFS= read -r line || [[ -n "$line" ]]; do
    printf '%s\n' "$line"
done < "file"
```

## File Conditionals Reference

| Test      | Description                   |
| --------- | ----------------------------- |
| `-e file` | File exists                   |
| `-f file` | Regular file exists           |
| `-d file` | Directory exists              |
| `-r file` | File is readable              |
| `-w file` | File is writable              |
| `-x file` | File is executable            |
| `-s file` | File size > 0                 |
| `-L file` | File is symbolic link         |
| `-h file` | File is symbolic link         |
| `-p file` | File is named pipe (FIFO)     |
| `-S file` | File is socket                |
| `-b file` | File is block special         |
| `-c file` | File is character special     |
| `-N file` | File modified since last read |

## File Comparison

| Test              | Description            |
| ----------------- | ---------------------- |
| `file1 -ef file2` | Same inode and device  |
| `file1 -nt file2` | file1 newer than file2 |
| `file1 -ot file2` | file1 older than file2 |

## Safe Temporary Files

```bash
# Create temp file
temp_file=$(mktemp)

# Create temp directory
temp_dir=$(mktemp -d)

# Cleanup on exit
trap 'rm -rf "${temp_file}" "${temp_dir}"' EXIT

# Use temp file
printf '%s\n' "data" > "${temp_file}"
```

## Read Without External Commands

```bash
# Read first line
IFS= read -r first_line < file

# Read specific line number
get_line() {
    local i=0
    while IFS= read -r line; do
        ((i++))
        ((i == $1)) && { printf '%s\n' "$line"; return; }
    done < "$2"
}

# Usage
get_line 5 /etc/passwd  # Get line 5
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.