ztouch – create empty files

Out of necessity I built a simple program that create many empty files. I put few examples how to use it in the code. Below command create exactly 1,000 empty files which mimic Nikon D200’s image files. The first file is DSC_00001.JPG, the last file is DSC_0999.JPG.

$ python ../ztouch.py DSC_0.JPG -r=1-999

Python version: 2.7.6
OS: Debian Wheezy 7.0

#!/usr/bin/env python
# 
#
#  Copyright (C) 2014  Hughe <janpenguin@riseup.net>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
# Date: 7/6/2014 
# File name: ztouch.py
# Version: 0.1 
# Description: 
# It simply creates empty files given by command line arguments.
# Usage examples are followed by.
# To create three a, b, and c files,
# $ ztouch a b c 
# To create ten files which start from 1 to 10, ho01 ... ho10
# $ ztouch ho -r=1-10
# To create dummy fifty JPG files from 100 to 150, 
# IMAGE_100.JPG ... IMAGE_150.JPG 
# $ ztouch IMAGE_.JPG -r=100-150
# 
# To do:
# 
# update file's timestamps like the touch program in GNU/Linux 
# Code clean up 
# create manual page


import sys
import argparse

class ArgumentParserError(Exception): pass

# Define error() that raises exception
class ArgumentParser(argparse.ArgumentParser):
    def error(self, message):
        raise ArgumentParserError(message)

def usage():
    p_n = sys.argv[0]
    title = 'usage:{} file1 [file2 ... ] [range]'.format(p_n)
    help_text = (title,
                'ztouch a b c',
                'ztouch DSC_.JPG -r=1-100')
    for s in help_text:
        print s

# touch implementation 
def touch(fname, times=None):
    import os
    try:
        with open(fname, 'a'):
            os.utime(fname, times)
    except OSError as (errno, errmsg):
        print 'ztouch():error({0}): {1}'.format(errno, errmsg)
        exit_msg = '{} creation is failed.'.format(fname)
        raise RuntimeError(exit_msg)

# Create multiple empty files
def create_file(names):
    try:
        fc = 0       # count number of files to be created
        for f in names:
            touch(f)
            print '{} is created.'.format(f)
            fc = fc + 1
    except Exception, err:
        sys.stderr.write('ERROR: {}\n'.format(str(err)))
    finally:
        print '{} files are created.'.format(fc)

# Create so many empty files 
def create_many_files(prefix, fromto):
    # the last number in the range is biggest. 
    m = fromto[-1]
    # length of zero strings 
    p_l = len(str(m))


    # Does the prefix string contain file extension?
    # Check dot string like .abc in it. 
    dot = '.'
    apply_extension = False
    l0 = []
    if prefix.find(dot) is not -1:
        z  = prefix.split(dot)
        if len(z[1]):
            l0.append(z[0])
            l0.append(z[1])
            apply_extension = True

    t = []
    if apply_extension:
        prefix0 = l0[0]
        ext = l0[1]
        for i in fromto:
            postfix = str(i).zfill(p_l)
            s = '{}{}.{}'.format(prefix0, postfix, ext)
            t.append(s)
    else:
        for i in fromto:
            postfix = str(i).zfill(p_l)
            s = '{}{}'.format(prefix, postfix)
            t.append(s)

    info0 = '{} files [{}, ..., {}] will be created.'.format(len(t),
                                                    t[0], t[-1])
    print info0
    q0 = raw_input('Press y to proceed.')
    if q0 == 'y':
        Name = tuple(t)
        create_file(Name)
    else:
        print 'Good Bye.'
    del t[:]

# Check the option -r value
# the input value should be a 'n1-n2' format string. 
# range value '1-2' suggests [1, 2]. But range(1,2) produces [1]. 
# Adding one to the end number resolves it.
def get_target_range(source):
    rawstr = source.split('-')
    if len(rawstr) is not 2:
        raise RuntimeError('Invalid range! Please try it again.')

    # Check number strings
    if rawstr[0].isdigit() and rawstr[1].isdigit():
        ab = map(int, rawstr)
        if max(ab) <= ab[0]:
            raise RuntimeError('Invalid range! Please try it again.')
        a = ab[0]
        b = ab[1] + 1
        return range(a, b)
    else:
        raise RuntimeError('non-integer strings! Please try it again.')

parser = ArgumentParser()
parser.add_argument("file_names", nargs='*', help="files to be created.")
parser.add_argument("-r", "--range", type=str, help="range of file names in sequential number.")

try:
    args = parser.parse_args()

    files = tuple(args.file_names)
    if len(files) is 0:
        raise ArgumentParserError('Need at least one file argument!')
    if args.range:    # create files in sequential order
        if len(files) is not 1:
            raise ArgumentParserError('range option needs one file name as \
prefix')
        prefix = files[0]
        fromto = get_target_range(args.range)
        create_many_files(prefix, fromto)
    else:               # create one or multiple files
        create_file(files)
except ArgumentParserError, e:
    print e.message
    usage()
except RuntimeError, e:
    print e.message
#
# end of source code
#

About janpenguin

Email: janpenguin [at] riseup [dot] net Every content on the blog is made by Free and Open Source Software in GNU/Linux.
This entry was posted in GNU/Linux, Python and tagged , , , , , , . Bookmark the permalink.

One Response to ztouch – create empty files

  1. livibetter says:

    If you ain’t writing this for *coding* Python, and supposedly that you have Bash and touch, then you can just do like

    $ touch DSC_{0001..0999}.JPG
    

    Bash’s Brace Expansion is one of my favorite features among all languages I have known.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s