Search code examples
sedsh

Delete last 162 lines in a series of files, rename files within forloop


I want to delete last 162 lines from a series of files with bash scripting.

for i in RMSF_CA_proA_*; do | tac $i | sed '1,162d' | tac >> tmp && mv tmp $i

This gives me error

bash: tac: command not found.

I also want to rename the files sequentially within the for loop.


Solution

  • This should work:

    #!/usr/bin/env sh
    
    # Fail on error
    set -o errexit
    # Enable wildcard character expansion
    set +o noglob
    
    # ================
    # CONFIGURATION
    # ================
    # File pattern
    FILE_PATTERN='RMSF_CA_proA_'
    # Lines to delete
    N_LINES=162
    
    # ================
    # MAIN
    # ================
    {
      # Check command 'sed' exists
      command -v sed > /dev/null 2>&1 || {
        printf "Command 'sed' not found\n" >&2
        exit 1
      }
      # Check command 'mv' exists
      command -v mv > /dev/null 2>&1 || {
        printf "Command 'mv' not found\n" >&2
        exit 1
      }
    
      index=0
      for file in "$FILE_PATTERN"*; do
        # Skip if not file
        [ -f "$file" ] || continue
    
        printf "Analyzing file '%s'\n" "$file"
    
        # https://stackoverflow.com/a/13383331/6676781
        # Delete last 'N_LINES' from 'file'
        sed \
          -i \
          -e :a \
          -e "\$d;N;2,${N_LINES}ba" \
          -e 'P;D' \
          "$file"
    
        # Rename 'file' to 'index'
        printf "Renaming file from '%s' to '%s'\n" "$file" "$index"
        mv "$file" "$index"
    
        # Increment index
        index=$((index = index + 1))
      done
    }
    

    Adjust the configuration parameters to your preference.
    Using sed, remove the last $N_LINES lines from $file (see this). The change is made in place, so there is no need to save the output and then modify the file.

    On Mac OS X sed command does not accept empty -i option. Therefore, add '' after -i (see this):

    sed \
      -i '' \