Skip to main content

How to Skip First Line

• 4 min read
bash

Quick Answer: Skip First Line in Bash

To skip the first line when processing a file in Bash, use tail -n +2 filename. For a loop, use read -r first to consume the header, then loop: read -r header; while read -r line; do ....

Quick Comparison: Header Skipping Methods

MethodSyntaxBest ForComplexity
tail -n +2tail -n +2 fileSimple skipVery simple
read firstread header; while read...LoopsSimple
sed 1dsed 1d filePipingSimple
awk NR>1awk 'NR>1' fileComplex logicModerate
skip/headhead -n -1 filePartial skipModerate

Bottom line: Use tail -n +2 for piping, use read for loops.


Overview

Many text files and data sources start with header lines that describe the columns or content but shouldn’t be processed as data. Whether you’re working with CSV files, log files, or command output, you’ll frequently need to skip the first line (or first N lines). This tutorial covers multiple efficient methods to skip header lines when processing files in Bash.

Method 1: Using tail Command

The tail command shows the last N lines of a file. By using -n +2, you skip the first line and process the rest:

# Skip first line and process rest
tail -n +2 filename.txt

# Skip first 3 lines
tail -n +4 filename.txt

# Example:
tail -n +2 data.csv | while read line; do
  echo "Processing: $line"
done

Example output:

# Input file (data.csv):
# Name,Age,City
# John,30,New York
# Jane,25,Los Angeles
# Bob,35,Chicago

$ tail -n +2 data.csv
John,30,New York
Jane,25,Los Angeles
Bob,35,Chicago

Method 2: Using read in while Loop

Skip the header by reading the first line separately before processing:

# Read header separately, then process data
read -r header < filename.txt
echo "Header: $header"

# Process remaining lines
while IFS= read -r line; do
  echo "Data: $line"
done < filename.txt

Or more explicitly:

while IFS= read -r line; do
  echo "Processing: $line"
done < <(tail -n +2 filename.txt)

Method 3: Using sed

The sed command can delete the first line before processing:

# Delete first line and process rest
sed '1d' filename.txt

# Delete first 3 lines
sed '1,3d' filename.txt

# Skip and process
sed '1d' data.csv | while read line; do
  echo "Processing: $line"
done

Example:

$ sed '1d' data.csv
John,30,New York
Jane,25,Los Angeles
Bob,35,Chicago

Method 4: Using awk

awk can easily skip header with the NR>1 condition:

# Process all lines except first
awk 'NR>1' filename.txt

# Skip first line and process specific fields
awk 'NR>1 {print $1, $2}' filename.txt

# With field separator for CSV
awk -F',' 'NR>1 {print $1}' data.csv

Example:

$ awk 'NR>1' data.csv
John,30,New York
Jane,25,Los Angeles
Bob,35,Chicago

# Extract just names
$ awk -F',' 'NR>1 {print $1}' data.csv
John
Jane
Bob

Practical Examples

Example 1: Process CSV File Skipping Header

#!/bin/bash

csv_file="$1"

if [ ! -f "$csv_file" ]; then
  echo "File not found"
  exit 1
fi

# Read CSV and process each line
tail -n +2 "$csv_file" | while IFS=',' read -r name age city; do
  echo "Name: $name, Age: $age, City: $city"
done

Input (employees.csv):

Name,Age,City
John,30,New York
Jane,25,Los Angeles

Output:

$ bash script.sh employees.csv
Name: John, Age: 30, City: New York
Name: Jane, Age: 25, City: Los Angeles

Example 2: Count Lines Excluding Header

#!/bin/bash

file="$1"

# Count lines excluding header
count=$(tail -n +2 "$file" | wc -l)
echo "Total records (excluding header): $count"

Output:

$ bash script.sh data.csv
Total records (excluding header): 5

Example 3: Process Multiple Files Skipping Headers

#!/bin/bash

# Process multiple CSV files, skipping headers
for csvfile in *.csv; do
  [ -f "$csvfile" ] || continue

  echo "Processing: $csvfile"

  # Skip header, process data
  awk -F',' 'NR>1 {print "User: " $1, "Email: " $3}' "$csvfile"
done

Example 4: Merge Multiple Files, Remove Duplicate Headers

#!/bin/bash

# Merge multiple CSV files keeping header from first file only
output_file="merged.csv"

# Process first file (include header)
cat "$1" > "$output_file"

# Process remaining files (skip headers)
shift
for file in "$@"; do
  tail -n +2 "$file" >> "$output_file"
done

echo "Merged into: $output_file"

Example 5: Process Log File Skipping Metadata

#!/bin/bash

log_file="$1"
skip_lines=${2:-3}  # Default skip 3 lines

echo "Skipping first $skip_lines lines of $log_file"

# Skip metadata lines and process log entries
tail -n +$((skip_lines + 1)) "$log_file" | while IFS= read -r line; do
  # Process each log line
  timestamp=$(echo "$line" | awk '{print $1, $2}')
  level=$(echo "$line" | awk '{print $3}')
  message=$(echo "$line" | cut -d' ' -f4-)

  echo "[$timestamp] $level: $message"
done

Example 6: Function to Process File Without Header

#!/bin/bash

# Reusable function to skip header
process_without_header() {
  local file="$1"
  local skip_count="${2:-1}"

  if [ ! -f "$file" ]; then
    echo "Error: File not found"
    return 1
  fi

  tail -n +$((skip_count + 1)) "$file"
}

# Usage
process_without_header "data.csv" 1 | while IFS=',' read -r field1 field2 field3; do
  echo "Processing: $field1"
done

Performance Comparison

For skipping headers in large files:

MethodSpeedMemoryBest For
tail -n +2Very FastLowSimple, one-liners
awk ‘NR>1’Very FastLowComplex processing
sed ‘1d’FastLowPiping, streaming
read in loopMediumLowSmall files

Best choice: Use tail -n +2 for simplicity, awk 'NR>1' for complex processing.

Handling Different Scenarios

Skip Variable Number of Lines

#!/bin/bash

file="$1"
skip_lines="${2:-1}"

echo "Skipping $skip_lines lines..."
tail -n +$((skip_lines + 1)) "$file"

Skip to Specific Line Number

# Skip to line 10
tail -n +10 filename.txt

# Process lines 5-15
sed -n '5,15p' filename.txt

Skip Based on Pattern

# Skip lines that start with '#' (comments)
grep -v '^#' filename.txt

# Skip empty lines
grep -v '^$' filename.txt

# Skip both empty and comment lines
grep -v '^[#[:space:]]*$' filename.txt

Key Points

  • Use tail -n +2 to skip first line efficiently
  • Use awk 'NR>1' for complex processing after skipping
  • Use sed '1d' when piping data through multiple commands
  • Remember that line counting starts at 1, not 0
  • Always check file existence before processing
  • Consider performance with very large files

Quick Reference

# Skip first line
tail -n +2 file.txt

# Skip first N lines
tail -n +$((N+1)) file.txt

# Skip with awk
awk 'NR>1' file.txt

# Skip with sed
sed '1d' file.txt

# Skip in CSV loop
while IFS=',' read -r f1 f2 f3; do
  echo "$f1 $f2 $f3"
done < <(tail -n +2 file.csv)
#!/bin/bash

file="$1"

# Method 1: Simple one-liner with tail
tail -n +2 "$file" | while IFS=',' read -r col1 col2 col3; do
  echo "Processing: $col1"
done

# Method 2: With file validation
if [ -f "$file" ]; then
  awk -F',' 'NR>1 {print $1, $2}' "$file"
else
  echo "Error: File not found"
  exit 1
fi