Ubuntu: Bash scripting to create next highest file


My task is to write a script that creates the next highest file in a particular directory. I have managed to sort the files in the directory so the script outputs the highest file name. For example from files red_01 red_02 red_03 it outputs red_04

My next task is to create the highest file so how can I make it create the red_04 file? Do I need to store the number in a variable and increment it somehow?


This will do what you need. Adjust the paths for whatever path you need, could use variables aswell and parse them into the script. But yeah you could adjust it yourself ;)

#!/bin/bash  #count your existing files  NUMBERATM=`find ./ -type f -name "red_*" | wc -l`  #add +1 to create the next higher file  NUMBERATM=$((NUMBERATM+1))    #check if it's below 10 since you need the 0 infront of it  if [ $NUMBERATM -lt "10" ]; then     var=0$NUMBERATM  else     var=$NUMBERATM  fi    #create your file  touch red_$var  


Without parsing ls or find output and without creating any extra files, incrementing the name of the last file only (the other files may have any names).

To count files in a directory:

stat * --printf "%i\n" | wc -l  

To get the last file:

i=0; j=$(stat * --printf "%i\n" | wc -l); for k in *; do (( (j - ++i) < 1 )) && echo "$k"; done  

(( (j - ++i) < 1 )) this tests how many times the loop has been run and compares it to the number of files in the directory. It relies on the fact that for loops over files in an ordered way.

To get the name of the next file assuming the pattern name_{01..99}

i=0  j=$(stat * --printf "%i\n" | wc -l)  for k in *; do     (( (j - ++i) < 1 )) &&     echo "${k%%_*}"_$(printf %02d "$(( ${k##*_} + 1 ))")  done  

To create the file:

touch $(i=0; j=$(stat * --printf "%i\n" | wc -l); for k in *; do (( (j - ++i) < 1 )) && echo "${k%%_*}"_$(printf %02d "$(( ${k##*_} + 1 ))"); done)  


touch $(    i=0    j=$(stat * --printf "%i\n" | wc -l)    for k in *; do       (( (j - ++i) < 1 )) &&      echo "${k%%_*}"_$(printf %02d "$(( ${k##*_} + 1 ))")    done  )  


Loop through numbers and check if file already exists. If it exists, go on with the loop; if file does not exist, create it.

for n in $(seq -w 01 99); do      [[ ! -f "red_${n}" ]] && { touch "red_${n}"; break; }  done  

Change to $(seq -w 001 999) or more digits if needed.

Note: This will create red_02 if missing, even if red_01 and red_03 exist.


This works even if gaps are present and event if numbers are not padded in filenames

#!/bin/bash    highest=-1  IFS="     "  for f in red_*; do      num=$(echo $f| cut -d _ -f2)      if [[ ! "$f" =~ red_[0-9]{1,2} ]];then #prevents failing because of                                                                        #spaces or letters          num=0      else          num=$(printf %d "$((10#$num))"); #eliminate zero padding to prevent                                            #interpretation as octal      fi        if [[ $num -gt "$highest" ]];then          highest=$num      fi  done    newfile=red_$(printf %02d $(($highest+1)))  echo $newfile  touch $newfile  


You could receive both the prefix and the desired amount of zero padding in the output as parameters, eliminating the literals "red_" and "02".

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »