DEV Community

Maksym
Maksym

Posted on

Nushell: paradigm shift in shells

Introduction

Nushell (nu) is a modern shell that treats data as structured information rather than plain text. It brings spreadsheet-like data manipulation to the command line with built-in support for JSON, CSV, YAML, and other formats.

Installation

Using Package Managers

# macOS with Homebrew
brew install nushell

# Windows with Winget
winget install nushell

# Linux with Snap
snap install nushell

# Cargo (Rust package manager)
cargo install nu
Enter fullscreen mode Exit fullscreen mode

From GitHub Releases

Download pre-built binaries from GitHub releases.

Basic Concepts

Structured Data Philosophy

Unlike traditional shells that work with text streams, Nushell works with structured data:

  • Everything is a table or structured data
  • Pipelines pass structured data between commands
  • Built-in understanding of common data formats

Starting Nushell

nu
Enter fullscreen mode Exit fullscreen mode

Core Commands and Navigation

This would be a basic commands, that all seasond developers are know, but the way that shell treats its output would suprise most of us. I leave this commands for the newcomers, who want to learn and to master basic commands.

File System Navigation

# List directory contents (structured output)
ls

# Change directory
cd /path/to/directory

# Present working directory
pwd

# Go back to previous directory
cd -

# Go to home directory
cd ~
Enter fullscreen mode Exit fullscreen mode

File Operations

# Create files
touch file.txt
"Hello World" | save hello.txt

# Copy files
cp source.txt destination.txt

# Move/rename files
mv oldname.txt newname.txt

# Remove files
rm file.txt

# Create directories
mkdir new-folder

# Remove directories
rmdir empty-folder
rm -rf folder-with-contents
Enter fullscreen mode Exit fullscreen mode

Working with Structured Data

Viewing Data

# View file contents
open data.json
open data.csv
open data.yaml

# View with pagination
open large-file.txt | less

# Get file info
ls | get name size modified
Enter fullscreen mode Exit fullscreen mode

Data Manipulation Commands

select - Choose specific columns

ls | select name size
ps | select name pid cpu
Enter fullscreen mode Exit fullscreen mode

where - Filter rows

ls | where size > 1mb
ps | where cpu > 50
ls | where name =~ "\.txt$"  # regex match
Enter fullscreen mode Exit fullscreen mode

sort-by - Sort data

ls | sort-by size
ls | sort-by modified --reverse
Enter fullscreen mode Exit fullscreen mode

group-by - Group data

ls | group-by type
ps | group-by user
Enter fullscreen mode Exit fullscreen mode

get - Extract specific values

ls | get 0        # First row
ls | get name     # All names
ls | get name.0   # First name
Enter fullscreen mode Exit fullscreen mode

length - Count items

ls | length
ps | where name =~ "python" | length
Enter fullscreen mode Exit fullscreen mode

first and last - Get specific rows

ls | first 5
ps | last 3
Enter fullscreen mode Exit fullscreen mode

skip and take - Pagination

ls | skip 10 | first 5  # Skip first 10, take next 5
Enter fullscreen mode Exit fullscreen mode

Data Formats

JSON

# Read JSON
open data.json

# Create JSON
{name: "John", age: 30} | to json

# Pretty print JSON
open data.json | to json --indent 2
Enter fullscreen mode Exit fullscreen mode

CSV

# Read CSV
open data.csv

# Create CSV
[{name: "Alice", age: 25}, {name: "Bob", age: 30}] | to csv

# Convert other formats to CSV
open data.json | to csv
Enter fullscreen mode Exit fullscreen mode

YAML

# Read YAML
open config.yaml

# Create YAML
{database: {host: "localhost", port: 5432}} | to yaml
Enter fullscreen mode Exit fullscreen mode

Variables and Configuration

Variables

# Set variables
let name = "John"
let numbers = [1, 2, 3, 4, 5]
let config = {host: "localhost", port: 8080}

# Use variables
echo $name
echo $numbers
echo $config.host
Enter fullscreen mode Exit fullscreen mode

Environment Variables

# View environment
env

# Set environment variable
$env.MY_VAR = "value"

# Use environment variable
echo $env.HOME
echo $env.PATH
Enter fullscreen mode Exit fullscreen mode

Configuration

# View current config
config

# Edit config file
config nu

# Set config values
config set table.mode rounded
Enter fullscreen mode Exit fullscreen mode

Advanced Features

Custom Commands

# Define a custom command
def greet [name: string] {
    $"Hello, ($name)!"
}

# Use the command
greet "World"

# Command with flags
def search [pattern: string, --case-sensitive] {
    if $case_sensitive {
        ls | where name =~ $pattern
    } else {
        ls | where name =~ $"(?i)($pattern)"
    }
}
Enter fullscreen mode Exit fullscreen mode

Aliases

# Create aliases
alias ll = ls -la
alias gs = git status
alias la = ls -a

# View aliases
alias
Enter fullscreen mode Exit fullscreen mode

Loops and Conditionals

# For loop
for file in (ls | get name) {
    echo $"Processing ($file)"
}

# Each (functional approach)
ls | each { |row| echo $"File: ($row.name)" }

# Conditional
if (ls | length) > 10 {
    echo "Many files"
} else {
    echo "Few files"
}
Enter fullscreen mode Exit fullscreen mode

Error Handling

# Try-catch equivalent
try {
    open nonexistent.txt
} catch {
    echo "File not found"
}

# Default values
open config.json | get database.port? | default 3000
Enter fullscreen mode Exit fullscreen mode

Working with External Commands

Running External Commands

# Run external commands
^ls -la
^git status
^python script.py

# Capture output as structured data
^ps aux | from ssv  # Space-separated values
Enter fullscreen mode Exit fullscreen mode

Parsing External Command Output

# Parse various formats
^kubectl get pods -o json | from json
^docker ps --format json | lines | each { from json }
Enter fullscreen mode Exit fullscreen mode

Useful Patterns and Examples

Log Analysis

# Parse log files
open server.log 
| lines 
| parse "{timestamp} {level} {message}"
| where level == "ERROR"
| group-by level
| length
Enter fullscreen mode Exit fullscreen mode

System Monitoring

# Monitor processes
ps | where cpu > 80 | sort-by cpu --reverse

# Check disk usage
ls | where type == dir | insert size_mb { |row| du $row.name | get physical | math sum | $in / 1mb }
Enter fullscreen mode Exit fullscreen mode

Data Processing

# CSV data analysis
open sales.csv
| group-by region
| each { |group| 
    {
        region: $group.0.region,
        total_sales: ($group | get sales | math sum),
        avg_sales: ($group | get sales | math avg)
    }
}
Enter fullscreen mode Exit fullscreen mode

Git Integration

# Git status in structured format
def git-status [] {
    ^git status --porcelain | lines | parse "{status} {file}"
}

# Branch information
def git-branches [] {
    ^git branch -v | lines | parse --regex "(?<current>[\*\s])\s+(?<name>\S+)\s+(?<hash>\S+)\s+(?<message>.*)"
}
Enter fullscreen mode Exit fullscreen mode

Configuration and Customization

Startup Configuration

Create ~/.config/nushell/config.nu:

# Custom prompt
$env.PROMPT_COMMAND = { 
    let path = ($env.PWD | str replace $env.HOME "~")
    $"(ansi green)($path)(ansi reset) > "
}

# Custom aliases
alias ll = ls -la
alias grep = rg
Enter fullscreen mode Exit fullscreen mode

Custom Completions

# Add to config.nu
def "nu-complete git-branches" [] {
    ^git branch | lines | each { |line| $line | str trim | str replace "* " "" }
}

extern "git checkout" [
    branch?: string@"nu-complete git-branches"
]
Enter fullscreen mode Exit fullscreen mode

Performance Tips

  1. Use structured commands instead of external parsing when possible
   # Good
   ls | where size > 1mb

   # Less efficient
   ^ls -la | from ssv | where size > 1mb
Enter fullscreen mode Exit fullscreen mode
  1. Pipeline efficiently
   # Filter early in pipeline
   ls | where type == file | where size > 1mb | sort-by size
Enter fullscreen mode Exit fullscreen mode
  1. Use built-in commands for data formats
   # Built-in JSON parsing is faster
   open data.json | get users.0.name
Enter fullscreen mode Exit fullscreen mode

Debugging and Help

Getting Help

# General help
help

# Command help
help ls
help where
help config

# List all commands
scope commands
Enter fullscreen mode Exit fullscreen mode

Debugging

# Debug mode
$env.RUST_LOG = "debug"

# Verbose output
ls --help

# Check command type
which ls
Enter fullscreen mode Exit fullscreen mode

Migration from Traditional Shells

Common Bash → Nu Patterns

# Bash: grep pattern file.txt
# Nu:
open file.txt | lines | where $it =~ "pattern"

# Bash: find . -name "*.txt" | wc -l
# Nu:
ls **/*.txt | length

# Bash: ps aux | grep python
# Nu:
ps | where name =~ "python"

# Bash: cat file.json | jq '.users[0].name'
# Nu:
open file.json | get users.0.name
Enter fullscreen mode Exit fullscreen mode

Conclusion

Nushell represents a paradigm shift in shell design, treating data as first-class citizens. Its structured approach makes data manipulation more intuitive and powerful than traditional text-based shells. Start with basic commands and gradually incorporate more advanced features as you become comfortable with the structured data philosophy.

And as always dont hesitate to leave your thoughts and criticize this article. Cheers!

Top comments (0)