15

I need a script that will create a file with the next file in a sequence. Each execution of the script should only create one file and the script could be run zero or more times on any given day. The files should be named after the current date in format %y%m%d with the second file having -01 appended, the third file to be created on a given date would have -02 etc. For example:

20170125.txt  // first file create on the day.
20170125-01.txt // 2nd file
20170125-02.txt // 3rd file

So far I've got this super basic script that creates my first daily file but I'm stumped as to how to do the incremental numbering after that.

#! /bin/bash

DATE=`date +%Y%m%d`
touch "$DATE.txt"
Greg B
  • 321

4 Answers4

19
today=$( date +%Y%m%d )   # or: printf -v today '%(%Y%m%d)T' -1
number=0

fname=$today.txt

while [ -e "$fname" ]; do
    printf -v fname '%s-%02d.txt' "$today" "$(( ++number ))"
done

printf 'Will use "%s" as filename\n' "$fname"
touch "$fname"

today gets today's date, and we initialise our counter, number, to zero and create the initial filename as the date with a .txt suffix.

Then we test to see if the filename already exists. If it does, increment the counter and create a new filename using printf. Repeat until we no longer have a filename collision.

The format string for the printf, %s-%02d.txt, means "a string followed by a literal dash followed by a zero-filled two-digit integer and the string .txt". The string and the integer is given as further arguments to printf.

The -v fname puts the output of printf into the variable fname.

The touch is just there for testing.

This will generate filenames like

20170125.txt
20170125-01.txt
20170125-02.txt
20170125-03.txt

etc. on subsequent runs.

Kusalananda
  • 333,661
6

You can use seq. It can create number sequences in variety of ways, however you need to know total number of files.

E.g: You can try seq -w 1 10. It will create the sequence from 01 to 10, then you can include it in a for loop:

for i in `seq -w 1 10`
do
  touch `date +%Y%m%d`-$i.txt
done

Addendum for your latest question update:

To accomplish what you want easily, you can create the first file with -0. On subsequent runs, you need to take the list of files, sort them, take the last one, cut it from last - and get the number, increment it and create the new file with that number.

Padding will need some more work though.

bayindirh
  • 979
  • I've updated the question with a bit more info. The script should only create one file on each execution, the file should have the next number in the sequence. – Greg B Jan 25 '17 at 11:04
  • 3
    There are more advanced facilities in Linux, like logrotate. They can do something similar automatically if you need. Your question needs some processing, so it may not be trivial with bash. That's why I asked the real reason. – bayindirh Jan 25 '17 at 11:05
  • 1
    @bayindirh logrotate is useful for rotating logs, but the question is about generating filenames, not rotating logfiles. – Kusalananda Jan 25 '17 at 11:58
  • 1
    I know, in first iteration of the question, aim was not clear. So I asked the question owner and he clarified. Please see the comments under the question too. I just didn't delete my comment to left the thing up in the air. – bayindirh Jan 25 '17 at 12:18
3

Something like...

#!/bin/bash
DATE=$(date +%Y%m%d)
filename="${DATE}.txt"
num=0
while [ -f $filename ]; do
    num=$(( $num + 1 ))
    filename="${DATE}-${num}.txt"
done
touch $filename

...should work. This creates filenames of the format DATE-1.txt, DATE-2.txt, DATE-3.txt, ..., DATE-10.txt, DATE-11.txt, etc. Changing that to DATE-01.txt etc is left as an exercise to the reader :)

Note that you should probably also make sure you don't call the script more than once concurrently, otherwise you'll have more than one script modifying things.

Side note: there is loads of software for managing multiple versions of a file. They're called "version control systems" (VCS), or "Source Control Management" (SCM). Git and subversion are pretty popular. I suggest you check them out, rather than reimplementing your own :-)

0

If you already have the counter value in an environment variable, you can use Bash arithmetic to generate the filename .... the $(( ctr+=1 )) increments the value of ctr, and substitutes the value in the filename string.

$ ctr=0
$ touch file-$(( ctr+=1 ))-name.txt
$ touch file-$(( ctr+=1 ))-name.txt
$ touch file-$(( ctr+=1 ))-name.txt
$ touch file-$(( ctr+=1 ))-name.txt
$ ls
file-1-name.txt  file-2-name.txt file-3-name.txt  file-4-name.txt
MikeW
  • 230
  • 3
  • 8