I am trying to write a script so that each time you execute it, it creates a batch of 10 files with increasing numbers starting with the last or max number that already exists. I was able to write a script to create 10 files but I am not sure what needs to be done so it increments from the last number every time we execute it.
#!bin/bash
num=1
while (($num <=10))
do
touch test$num
((num ))
done
It just creates 10 files (test1 , test2..). I understand I would need to do a file check and see if the file exists and then increment the largest number with 1. But where do I start?
CodePudding user response:
Try this Shellcheck-clean code:
#! /bin/bash -p
# Find maximum number already in use
max=0
for tf in test[0-9]*; do
num=${tf#test}
[[ $num != *[^0-9]* && num -gt max ]] && max=$num
done
# Create 10 files with numbers starting at max 1
for ((i=1; i<=10; i )); do
touch "test$((max i))"
done
CodePudding user response:
You have to use a shell glob for getting the previous files; unfortunately, the implicit sort of shell globing isn't numerical (for example test2
will be considered bigger than test10
) so you'll have to use an other way to get the last number of the previous batch.
#!/bin/bash
shopt -s extglob nullglob
prefix=test
batch_size=10
old_files=( "$prefix" ([0-9]) )
last=$(printf '%s\n' "${old_files[@]#"$prefix"}" | sort -nr | head -n 1)
declare -a new_files="( $prefix{$((last 1))..$((last batch_size))} )"
touch "${new_files[@]}"
I've probably made the code overly complicated for a beginner, so here are some details for helping you understand it:
shopt -s extglob nullglob
allows the use of bash extended globing and forces null expansion for unmatched globs.old_files=( "$prefix" ([0-9]) )
creates a bash array containing all the files that start with the givenprefix
, followed by one or more digits; btw, the construct(...)
isn't a standard glob but a bash extended one."${old_files[@]#"$prefix"}"
expands to all the files, stripped from theirprefix
.declare -a new_files="( $prefix{$((last 1))..$((last batch_size))} )"
creates an array containing the new batch of files.
It uses adeclare
trick for expanding a bashrange
with variables in it; a bash range is for exampletest{1..3}
(which expands totest1 test2 test3
), and the problem with it is that you can't use variables inside the curly brackets (for example{$min..$max}
).
Here's an easier solution (but less robust and less performant):
#!/bin/bash
last=$(
printf '%s\n' test* |
sed -nE 's/^test([0-9] )$/\1/p' |
sort -rn |
head -n 1
)
for ((i = last 1, j=last 10; i <= j; i ))
do
touch "test$i"
done
CodePudding user response:
I can tell you in general terms what you will need.
You need two variables. A per-execution count variable, which you've already got, and an overall count variable, which you will need to store outside of the script itself; ideally just in another local text file.
Then, import the overall count variable to the script, execute the script, increment the overall count variable by ten, and export the overall count back out to the separate file.