Forwardslash /

Beta
TAGS: code lit-tech

Newdiary

A Writer's Shell Script

This script is the most useful little program I’ve written: I use it almost every day. It’s a good example of how useful a tiny shell script can be.

For years I’ve been keeping a diary almost daily, and my process was always to create a file with today’s date, open it up, and type today’s date into the top before beginning to write. Not a horrible chore, but certainly monotonous and distracting from what I’d rather do, which is just have a thought and immediately begin writing it down.

Now, I just open the terminal, enter a single command and then I’m writing.

Here’s the code in its entirety and then I’ll dissect it.

#!/bin/sh

date_formatted=$(date +%Y-%m-%d)

text_file=$date_formatted.txt

day=$(date +%d)
month=$(date +%m)
year=$(date +%y)

#echo $month"/"$day"/"$year

if [ -e $text_file ]
  then 
    # Output message - terminating file creation
    printf "\e[31m"
    echo ""
    echo "  Today's diary file already exists."
    echo "  ----------------------------------"
    echo ""
    printf "\e[m"
  else 
    # Output message - proceeding with file creation
    printf '\e[35m'
    echo ""
    echo "  Creating today's diary"
    echo "  ----"$text_file"----"
    echo "  * * * * * * * * * * * *"
    echo ""
    printf "\e[m"
    # Create file   
    touch $text_file
    # Place today's date in the file    
    echo $month"/"$day"/"$year >> $text_file
    echo "" >> $text_file
    echo "" >> $text_file
    open -a "Byword" $text_file
fi

If you’re as new to shell scripting as I was recently, you’ll need to know about a couple steps: adding a folder to your path, changing the type of file to make it executable. It’s nothing too horribly difficult, and there’s loads of info about it online. So, you’d start with a file with the name of the command – in this case “newdiary” – and the first line of code, #!/bin/sh just tells your Mac (I think this script would work on Unix/Linux but I haven’t tried it) that the file is a shell script.

There’s a bunch of this kind of code (printf “\e[31m”) in the script whose sole purpose is to pretty up the script with ANSI colors. So here’s the script again without those – a bit shorter and clearer.

#!/bin/sh

date_formatted=$(date +%Y-%m-%d)

text_file=$date_formatted.txt

day=$(date +%d)
month=$(date +%m)
year=$(date +%y)

#echo $month"/"$day"/"$year

if [ -e $text_file ]
  then 
    # Output message - terminating file creation
    echo ""
    echo "  Today's diary file already exists."
    echo "  ----------------------------------"
    echo ""
  else 
    # Output message - proceeding with file creation
    echo ""
    echo "  Creating today's diary"
    echo "  ----"$text_file"----"
    echo "  * * * * * * * * * * * *"
    echo ""
    # Create file   
    touch $text_file
    # Place today's date in the file    
    echo $month"/"$day"/"$year >> $text_file
    echo "" >> $text_file
    open -a "Byword" $text_file
fi

So here’s the important stuff.

date_formatted=$(date +%Y-%m-%d)

text_file=$date_formatted.txt

The above code first creates a variable that holds today’s date formatted like this: 2013_02_24. Then it adds a .txt file extension onto it and sends that into a variable called text_file. So this is where I’m getting the file name of today’s diary file. Dumped into a folder, it will always sort chronologically, and I don’t even have to think about what day it is.

day=$(date +%d)
month=$(date +%m)
year=$(date +%y)

#echo $month"/"$day"/"$year

And here’s another set of variables for outputting the date. This is to save me the trouble of typing in the date in this format: 2/24/2012 at the top of the file. The line underneath the variables puts it all together, commented out but there for reference.

if [ condition ]
  then
    # do something
  else
    # do something else
fi

The rest of the script is wrapped in an if / else statement. In bash, these are started with if and ended with fi – “if” backwards. Brackets aren’t necessary.

if [ -e $text_file ]

So what’s the condition I’m testing for? First I need to make sure if I already started a diary file for today, I don’t overwrite it. The command line is powerful – you can obliterate things without meaning to. So here, bash understands the -e as testing whether what’s immediately following it exists, and I’m asking it to check for the filename with today’s date on it.

  then 
    # Output message - terminating file creation
        echo ""
    echo "  Today's diary file already exists."
    echo "  ----------------------------------"
    echo ""

If it does, I want to abort. The echo "" lines are just putting in some spacing, and so if the file exists all I’m doing is sending an output message to the terminal and then quitting.

  else 
    # Output message - proceeding with file creation
    echo ""
    echo "  Creating today's diary"
    echo "  ----"$text_file"----"
    echo "  * * * * * * * * * * * *"
    echo ""
    # Create file   
    touch $text_file
    # Place today's date in the file    
    echo $month"/"$day"/"$year >> $text_file
    echo "" >> $text_file
    open -a "Byword" $text_file

If it doesn’t already exist, then I want to go ahead with my script. The comments explain what’s happening where. First I echo out a message to the terminal. Then with the touch command I create a file with the filename of today’s date.

Then, I echo out today’s date in the second format I created above so I don’t have to type it into the file. The >> operator directs the output into the text file and not to the terminal screen. Then I throw in an extra blank line for good measure.

Finally, the open command opens the file. With the -a “Byword” option I’m telling it to open up in an application with the name of my favorite word processor of the moment. And using the filename variable again, I’m telling it what to open.

There you have it – a super-useful shell script for any writer who keeps a regular diary. There are tons of other repetitive tasks writers and editors do, especially if they’re doing their own digital publishing, that could benefit from scripts like this one.