0

I was taking an online assessment and I got the below question.

  • Create a script located at /usr/local/bin/set-file-extensions that will change the extension of all files in the directory /var/dump/files based on user input.
  • The script should support the option flag -E that will allow a user to pass a three character extension(.i.e log).
  • If a non three character extension is passed by the user, display the error "Invalid input. A three character extension is required." and exit with a status code of 19.
  • Once that file extension is received, the script should rename all files under the directory /var/dump/files with the given extension. I.e. A file named myfile should be renamed as myfile.log.
  • 1
    Code Review would be a better venue if you have a script performing such a specific task and want it reviewed. – Gilles Aug 20 '14 at 21:20
  • @Gilles, thanks. I was thinking that the script that I had, satisfied the criteria mentioned in the question. But apparently, it has quiet few flaws as pointed out by Stephane. I should try and modify them and the reason for posting it here is, I like it better here :) – Ramesh Aug 20 '14 at 21:28
1

You didn't specify that it had to be a bash solution so here is a python solution. It takes into account that you require a 3 character extension. However it doesn't do much in the way of checking you wont break anything. It does check for directories and that you are only going to rename real files. This solution will require an -E option to be passed in.

edit:

If filename starts with a . (hidden file) ignore. With regards to symlinks, that might take a little more thought.

#!/usr/bin/env python

import sys
import argparse
import re
import os

def main():
    path = '/var/dump/files'
    parser = argparse.ArgumentParser()
    parser.add_argument('-E', help='three character extension(.i.e log)',\
         type=str)
    args = parser.parse_args()

    if args.E:
        if not re.search(r'^[a-zA-Z]{3}$', args.E):
            print 'Invalid Input. A three character extenstion required: %s' % str(args.E)
            sys.exit(19)
        ext = '.'+str(args.E)
    else:
        print 'Invalid Input. A three character extenstion required'
        sys.exit(19)

    files = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path,f))]
    for f in files:
        # ignore hidden files
        if f[0] == '.': continue
        name = f.split('.')[0]
        os.rename(os.path.join(path,f),os.path.join(path,name+ext))



if __name__ == "__main__":
    main()

This solution the -E will be option, and use '.log' as a default. You could specify Required=True in the add_argument() to have it as a required option.

#!/usr/bin/env python

import sys
import argparse
import re
import os

def main():
    path = '/var/dump/files'
    parser = argparse.ArgumentParser()
    parser.add_argument('-E', help='three character extension(.i.e log)',\
         type=str)
    args = parser.parse_args()

    if args.E:
        if not re.search(r'^[a-zA-Z]{3}$', args.E):
            print 'Invalid Input. A three character extenstion required: %s' % str(args.E)
            sys.exit(19)
        ext = '.'+str(args.E)
    else:
        ext = '.log'

    files = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path,f))]
    for f in files:
        # ignore hidden files
        if f[0] == '.': continue
        name = f.split('.')[0]
        os.rename(os.path.join(path,f),os.path.join(path,name+ext))



if __name__ == "__main__":
    main()
  • [a-zA-Z] matches an ASCII latin letter, not a character. Note that isfile checks for regular (or symlink to regular) files, not the other types of files. It will rename all the hidden files (.cvsignore, .foo.bar) to ext. – Stéphane Chazelas Aug 21 '14 at 9:49
0

I ended up creating a script like below.

#!/bin/bash
while [[ $# -ge 1 ]]
do
    key="$1"
    shift
    case $key in
    -E)
        EXTENSION="$1"
        length=$(expr length "$EXTENSION")
        if [ $length != 3 ]
        then
            (exit 19); echo "Invalid Input. A three character 
            extension is required. Exit status:$?"
        else
            for f in /var/dump/files/*; do
                mv -- "$f" "${f}.$EXTENSION"
            done
        fi
        shift
    ;;
    *)
        (exit 19); echo "Invalid Option selected. Exit status:$?"
    ;;
    esac
done

References

https://stackoverflow.com/a/14203146/1742825

  • Close, I believe that -E is an optional parameter. The OP stated as one of the conditions: "based on user input"....I see no user input being reqested but I do see the enforcement of the -E parameter. Agree it is an interpretation issue. – mdpc Aug 20 '14 at 19:16
  • 2
    What about -Efoo. You should use getopts. – Stéphane Chazelas Aug 20 '14 at 19:46
  • case $var in ???) or [ "${#var}" -eq 3 ] for var length. GNU expr gives you the length in bytes, not characters and has trouble for values like + or index... – Stéphane Chazelas Aug 20 '14 at 19:50
  • You should validate all the arguments before starting the job. – Stéphane Chazelas Aug 20 '14 at 19:50
  • * doesn't match all files, just the non-hidden ones. It also expands non-regular files like directories or sockets (the requirements are not clear on that). – Stéphane Chazelas Aug 20 '14 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.