Running Script Files
Execute a shell script by passing it as a positional argument:
Nash reads the script from the host filesystem (not the VFS), parses it line-by-line, and executes each command in sequence.
Basic Script Example
Create a file hello.sh:
#!/usr/bin/env nash
echo "Starting script..."
mkdir -p /tmp/test
cd /tmp/test
echo "Hello from Nash!" > greeting.txt
cat greeting.txt
ls -l
Run it:
Output:
Starting script...
Hello from Nash!
-rw-r--r-- greeting.txt 18 bytes
Scripts execute inside Nash’s sandboxed VFS environment. They cannot access host files unless explicitly mounted with --bind.
Shebang Handling
Nash automatically ignores shebang lines (lines starting with #!) on line 1 of any script:
#!/usr/bin/env nash
echo "This works fine"
The shebang is skipped during execution. This means you can make scripts executable and run them directly:
chmod +x script.sh
./script.sh # Still runs with nash if called with nash
Making scripts executable and running them with ./script.sh invokes the host shell interpreter specified in the shebang. To run with Nash, always use nash script.sh.
One-Shot Commands (-c)
Execute a single command string and exit using the -c flag:
nash -c "echo hello | grep hello"
Output:
This is identical to bash’s -c behavior.
Complex One-Liners
You can use the full Nash syntax in -c mode:
Pipes and redirections
Command chaining
Conditional execution
Variable expansion
nash -c "echo 'apple\nbanana\napple' | sort | uniq -c"
Quoting in -c Mode
Be mindful of shell quoting when using -c from bash:
nash -c 'echo $USER' # Single quotes: Nash expands $USER
nash -c "echo \$ USER" # Escaped $: Nash expands $USER
nash -c "echo hello | grep hi" # Pipe preserved for Nash
nash -c "echo $USER " # Host bash expands $USER before Nash sees it
nash -c echo hello # -c expects a single argument
Reading from Stdin (-s)
Use the -s flag to read commands from stdin line-by-line:
cat commands.txt | nash -s
or
Example: Batch Processing
Create commands.txt:
mkdir -p /tmp/batch
echo "Processing file 1" > /tmp/batch/file1.txt
echo "Processing file 2" > /tmp/batch/file2.txt
ls /tmp/batch
cat /tmp/batch/file1.txt
Execute:
Output:
file1.txt file2.txt
Processing file 1
Combine -s with heredocs for inline script execution:
nash -s << 'EOF'
echo "Starting batch job"
mkdir -p /tmp/work
cd /tmp/work
echo "data" > input.txt
cat input.txt | grep data
EOF
When using -s, Nash reads stdin regardless of whether it’s a TTY. Combine with -i if you want interactive mode after stdin is exhausted (though this is rare).
Shell Flags for Scripts
Nash supports bash-compatible shell flags that modify script execution behavior:
Exit on Error (-e)
Stop execution immediately if any command returns non-zero:
Example script.sh:
echo "Step 1"
false # This fails
echo "Step 2" # NEVER executed with -e
With -e:
nash -e script.sh
# Output:
# Step 1
# nash: errexit: command exited with status 1
Without -e:
nash script.sh
# Output:
# Step 1
# Step 2
Undefined Variable Errors (-u)
Treat references to unset variables as errors:
Example:
echo "User: $USER " # OK: $USER is set
echo "Missing: $FOOBAR " # ERROR with -u: FOOBAR not set
Trace Execution (-x)
Print each command to stderr before executing (set -x):
Example script:
echo "hello"
mkdir /tmp/test
Output with -x:
+ echo "hello"
hello
+ mkdir /tmp/test
Print each line as it’s read:
This shows the raw input before any parsing or execution.
Combining Flags
Flags can be combined for robust script execution:
nash -eux script.sh # errexit + nounset + xtrace
This is equivalent to the common bash pattern:
Script Examples
Data Processing Pipeline
process.sh:
#!/usr/bin/env nash
# Generate sample data
echo "apple" > /tmp/fruits.txt
echo "banana" >> /tmp/fruits.txt
echo "apple" >> /tmp/fruits.txt
echo "cherry" >> /tmp/fruits.txt
# Process: sort, dedupe, count
cat /tmp/fruits.txt | sort | uniq -c
# Find specific items
grep "apple" /tmp/fruits.txt | wc -l
Run:
Conditional Logic
check.sh:
test -f /etc/hostname && echo "Hostname file exists" || echo "Missing"
test -d /home/user && cd /home/user && pwd
test -z " $CUSTOM_VAR " && echo "CUSTOM_VAR is not set"
Run with environment override:
nash -E CUSTOM_VAR=value check.sh
Working with Host Files
analyze.sh:
#!/usr/bin/env nash
# Access host directory via mount
cd /data
find . -name "*.txt" -type f
cat report.txt | grep ERROR | wc -l
Run with mounted host directory:
nash --bind ./project-data:/data analyze.sh
Without a --bind mount, scripts cannot access host filesystem paths. The script will operate entirely within the VFS sandbox.
Script Error Handling
Parse Errors
If a line has invalid syntax, Nash reports the error and continues (unless -e is set):
echo "valid"
this is | bad syntax
echo "continues without -e"
Output:
valid
nash: parse error: unexpected token
continues without -e
With -e:
nash -e script.sh
# Output:
# valid
# nash: parse error: unexpected token
# nash: errexit: parse error
Exit Codes
Scripts return the exit code of the last executed command:
nash script.sh
echo $? # Host shell exit code from nash
Advanced Usage
Login Shell Scripts
Combine -l with script execution to source rc files first:
This sources /etc/profile and ~/.nashrc (from VFS) before running the script.
Custom RC with Script
nash --rcfile ./setup.nashrc script.sh
Environment Injection
Pass environment variables to scripts:
nash -E DEBUG= true -E API_URL=http://localhost script.sh
The script can access $DEBUG and $API_URL.
See Also