0

Hello. I know there are similar topics here, but to be honest I didn't find solution for my problem. I've also checked stackoverflow but no result.

  1. I have to make a bash script that will be changing files' names from lower to upper OR from upper to lower via parameters in command line. So when I put in command line:

    ./bashScript lower upper

    then all files in directory should change from lower to upper case.

  2. I have to also add 3rd parameter that will let me change only one specific file. So for example I have to be able of putting in command line:

    ./bashScript lower upper fileName

I've created something like this:

#!/bin/bash

if test "$1" = "lower" && test "$2" = "upper"
then
for file in *; do
    if [ $0 != "$file" ] && [ $0 != "./$file" ]; then
    mv "$file" "$(echo $file | tr [:lower:] [:upper:])";
    fi
fi
done

elif test "$1" = "upper" && test "$2" = "lower"
then
for file in *; do
if [ $0 != "$file" ] && [ $0 != "./$file" ]; then
mv "$file" "$(echo $file | tr [:upper:] [:lower:])";
fi
done
fi

But this is not working at all. And I don't know how to make this 3rd parameter for one specific file. I'd be grateful if anyone could write a code or add to my code proper issues.

Thank you in advance.

3

Have a look at this:

#!/bin/bash

if [[ "$1" == "lower" && "$2" == "upper" ]] ; then
    EXPRESSION="y/a-z/A-Z/"
elif [[ "$1" == "upper" && "$2" == "lower" ]] ; then
    EXPRESSION="y/A-Z/a-z/"
else
    echo "Usage:     $0 lower upper [file]     OR     $0 upper lower [file]"
    exit 1
fi


if [[ -z "$3" ]] ; then
    shopt -s dotglob
    rename "$EXPRESSION" ./*
else
    rename "$EXPRESSION" "$3"
fi

You should normally use [[ ... ]] double brackets for conditional expressions in Bash. Inside them you can use e.g. == to compare for string equality (with both sides quoted), or && to combine two conditions with a logical AND.

Then, I decided to use the rename command instead of your construction with echo, tr and mv. It takes a "Perl expression" as first argument and any number of file names (like e.g. a shell glob result) after that and will rename all matching files accordingly.

The Perl expression that changes all lowercase letters in a name to uppercase letters is e.g. y/a-z/A-Z/. y is the command and means to translate all characters. a-z is a notation that matches all lowercase latin characters, A-Z for uppercase. Depending on the script arguments, we store either the expression for converting to upper- or to lowercase in the shell variable $EXPRESSION.

Then we check if a third script argument was given (-z is a Bash conditional check that is true if a string is empty). If not, we call the rename command with our stored expression and a ./* as shell glob to match all files in the current directory. The dotglob shell option we enabled before that makes sure this also matches hidden files with names that start with a dot, otherwise those would be omitted. However, if a third script argument was given, we pass that one on as argument.

  • So this code will be working only with Perl? Because I wonder if it can work with vim. – paweljvn Nov 23 '18 at 20:23
  • 2
    @paweljvn, You can use any editor to create the shellscript file (copy and paste the code from this answer). Then you can make the shellscript executable with chmod and run it in a terminal window. Please notice the first line #!/bin/bash, which indicates that it will be executed by the shell program bash. You will not need perl explicitly, but it is common, that a perl version of rename will be used. (Perl is available as part of Ubuntu, so you need not worry about that.) – sudodus Nov 23 '18 at 20:57
  • @sudodus The 'rename' function is not found in my bash. Any ideas? – paweljvn Nov 24 '18 at 21:22
  • @paweljvn It came preinstalled for me, but maybe you have to install that tool manually with sudo apt install rename first. – Byte Commander Nov 24 '18 at 21:31
  • @ByteCommander That works! Do you know how can I add function that will be changing all files from lower to upper (or reverse) if I don't put a name of file? – paweljvn Nov 24 '18 at 21:38
0

I thought i would add my two pence worth, slightly different take on Byte Commander's answer.

#! /bin/bash

case $1 in
upper)  
    # check second argument to process a file if one given or the whole directory
    if [[ $2 > '' ]] #check if the second parameter is used (filename)
    then
        if [ -f $2 ] #check if the file exists
        then
            mv "$2" "$(echo $2 |tr [:lower:] [:upper:])" 
        else
            echo "$2 does not exist"
        fi          
    else    
        # process the whole directory
        for file in * 
        do
                if [ $0 != "$file" ] && [ $0 != "./$file" ]
            then
                    mv "$file" "$(echo $file | tr [:lower:] [:upper:])"
                fi
        done
    fi;;
lower)
    # check second argument to process a file if one given or the whole directory 
    if [[ $2 > '' ]] 
    then
        if [ -f $2 ] #check if the file exists
        then
            mv "$2" "$(echo $2 |tr [:upper:] [:lower:])" 
        else
            echo "$2 does not exist"
        fi          
    else    
        #process the whole directory
        for file in *; 
        do
                if [ $0 != "$file" ] && [ $0 != "./$file" ]
            then
                    mv "$file" "$(echo $file | tr [:upper:] [:lower:])"
                fi  
        done
    fi;;

--help)
    echo "Usage: $0 lower to lowercase entire directory "
    echo "Usage: $0 uppper to uppercase entire dirctory "
    echo "Usage: $0 lower [file] or upper [file] for a specific file"
    exit 1;;
esac

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.