'Create a batch of 10 files with increasing numbers starting with the last or max number that already exists
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?
Solution 1:[1]
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
num=${tf#test}extracts the number from the file name by removing thetestprefix. See Removing part of a string (BashFAQ/100 (How do I do string manipulation in bash?)).[[ $num != *[^0-9]* && num -gt max ]] && max=$numfirst checks that$numis really a number (i.e. it does not contain a non-numeric character. A non-numeric$numcould occur if the directory contained a file with a name liketest5a($numwould be5a, which is not a number). (See [[...]] in the Bash Reference Manual for details of the pattern matching capabilities (=/==and!=) of the[[...]]conditional construct.)
It then checks if the number in variablenumis greater than the maximum number seen so far. (Bash allows$prefixes to be omitted with arithmetic expressions (including-gtinside[[...]]) so it's not necessary to write$num -gt $max).
If both checks pass then the maximum number seen so far is updated.
Solution 2:[2]
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 nullgloballows 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.
I use a trick withdeclarefor expanding a bashrangewith variables in it; a bash range is for exampletest{1..3}, which expands totest1 test2 test3, and the problem with it is that you normally can't use variables inside the curly brackets (ex.{$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
Solution 3:[3]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | John Kugelman |
