StoneThrow
StoneThrow

Reputation: 6255

What is efficient way to ensure bash script variable is valid permission bits?

I'm inexperienced with bash scripts, mostly cobbling things together from google searches. The following simple script creates file foo and changes its permission bits to whatever the script's $1 is. Can an experienced bash scripter please advise what would be a proper and/or efficient way to ensure that $1 is valid permission bits, i.e. a valid arg1 to chmod?

#!/bin/sh
#mkfoo.sh

if [ $# -eq 0 ]
then
  return
fi

perm=$1

touch ./foo
chmod "${perm}" ./foo

As part of my inexperience, I'm unclear when/why variables are strings or integers. A string-validation approach feels infeasible because of the number of values the permission bits could be. What comes to mind is that I'd want to validate whether $1 is an integer, and if so, that it's between 0 and 777. But I'm unclear if that's a sufficient/efficient validation: I've got a rudimentary understanding of linux file permissions, and I'm led to believe there are lots of subtleties. Grateful for help.

Upvotes: 1

Views: 99

Answers (4)

Stephen P
Stephen P

Reputation: 14800

This script will accept any valid permissions that chmod allows.
It will create the file (if it doesn't already exist) and attempt to set the permissions. If setting the permissions fails the file is removed.
It requires exactly two arguments; the filename to create and the permissions to set.

This allows you to use symbolic or 4-digit permissions, such as create foo u+x,g+rwx (assuming the script is named "create") or create foo 2640

This is pretty simple, as an example. I often include a usage() function which I would call in place of the first echo. You could also include default permissions if the seconds argument was omitted.

#!/bin/sh

if [ $# -ne 2 ]
then
    echo "output a usage message, don't just return"
    exit
fi

if [ -e "${1}" ]
then
    echo "${1} already exists"
    exit
fi

touch ./"${1}"

if chmod "${2}" "${1}" > /dev/null 2>&1
then
    echo "${1} created with permissions ${2}"
else
    rm "${1}"
    echo "${1} not created: invalid permissions: ${2}"
fi

Upvotes: 1

sripley
sripley

Reputation: 125

As others have mentioned, chmod does its own validation so it'd probably be best to just use that, but if you absolutely want to do this in a way similar to the code you provided you can do:

#!/bin/sh
if [ $# -eq 0 ]
then
    echo "Invalid input"
    exit 1
fi

if ! [[ $1 =~ [0-7][0-7][0-7] ]]
then
    echo "Invalid input"
    exit 1
else
    perm=$1
fi

touch ./foo
chmod "${perm}" ./foo

This will ensure that each digit is valid.

Upvotes: 0

Barmar
Barmar

Reputation: 780949

If you only want to allow numeric permissions, you can check them with a pattern check:

case "$perms" in 
    [0-7][0-7][0-7]) 
        touch ./foo
        chmod "${perm}" ./foo
        ;;
    *) 
        echo "Invalid permissions $perms"
        ;;
esac

Upvotes: 4

jeremysprofile
jeremysprofile

Reputation: 11435

From your comments, your goal is to give up on the chmod if the permissions specified are invalid.

chmod "$1" ./foo 2>/dev/null

2 is the file descriptor for stderr. Redirecting to /dev/null will let it fail silently. chmod, as stated in the comments, does its own validation on if the permissions are acceptable.

Upvotes: 3

Related Questions