Skip to content

Instantly share code, notes, and snippets.

@jmkim
Last active October 5, 2016 06:47
Show Gist options
  • Save jmkim/b10fc129ff24bb3f0eb43598d21146c4 to your computer and use it in GitHub Desktop.
Save jmkim/b10fc129ff24bb3f0eb43598d21146c4 to your computer and use it in GitHub Desktop.
Batch change the mode bit (the permission of files and directories)
#!/bin/bash
# Batch change the mode bit (the permission of files and directories)
#
# USAGE: script_name [path1] [path2]...
# script_name
#
# Author: Jongmin Kim (kdzlvaids@gmail.com)
#
# Settings
#
# Verbose mode
#
# Default value: 1
# Available values:
# 0 Disable
# 1 Enable
export verbose=1
# Scan the executable file
# Recognise the executable file, and use $modebit_exec instead of
# $modebit_file. This will slow down the processing speed.
#
# Default value: 1
# Available values:
# 0 Disable
# 1 Enable
export enable_execscan=1
# Mode bit for a directory
#
# Default value: $(expr 777 - $(umask))
export modebit_dir=$(expr 777 - $(umask))
# Mode bit for a file
#
# Default value: $(expr 666 - $(umask))
export modebit_file=$(expr 666 - $(umask))
# Mode bit for an executable file
#
# Default value: $(expr 777 - $(umask))
export modebit_exec=$(expr 777 - $(umask))
#
# Functions
#
# Functions for printing the string
echo_success() { ( echo "'$1' to $2$3..." ) } # $1:path $2:mode $3:comment
echo_warn() { (>&2 echo "Warning: '$1' is $2. Skipping..." ) } # $1:path $2:type
echo_warn_not_found() { (>&2 echo "Warning: File '$1' not found. Skipping..." ) } # $1:path
echo_error_not_found() { (>&2 echo "Error: File '$1' not found." ) } # $1:path
# Function for setting the mode bit
set_mode()
{
workpath=$1
# The file is not owned by the user. Skip
if [[ ! -O "$workpath" ]]; then
echo_warn "$workpath" "not owned by the user"
# The file is a directory.
elif [[ -d "$workpath" ]]; then
if [[ $verbose -eq 1 ]]; then
echo_success "$workpath" $modebit_dir " (directory)"; fi
chmod $modebit_dir "$workpath"
# The file is an executable file.
elif [[ $enable_execscan -eq 1 ]] && [[ $(file "$workpath") =~ (executable) ]]; then
if [[ $verbose -eq 1 ]]; then
echo_success "$workpath" $modebit_exec " (executable)"; fi
chmod $modebit_exec "$workpath"
# The file is a regular file.
elif [[ -f "$workpath" ]]; then
if [[ $verbose -eq 1 ]]; then
echo_success "$workpath" $modebit_file; fi
chmod $modebit_file "$workpath"
# The file is a symbolic link. Skip
elif [[ -h "$workpath" ]]; then
echo_warn "$workpath" "a symbolic link"
# The file is a device file. Skip
elif [[ -b "$workpath" ]] || [[ -c "$workpath" ]]; then
echo_warn "$workpath" "a device file"
# The file is a named pipe (FIFO). Skip
elif [[ -p "$workpath" ]]; then
echo_warn "$workpath" "a named pipe"
# Nevermind
elif [[ -e "$workpath" ]]; then
echo_warn "$workpath" "undefined"
# Nevermind
else
echo_warn_not_found "$workpath"
fi
}
find_exec()
{
find "$@" -exec bash -c 'for workpath do set_mode "$workpath"; done' sh {} +
}
# Export the functions to use them in the inherited function
export -f echo_success
export -f echo_warn
export -f echo_warn_not_found
export -f echo_error_not_found
export -f set_mode
#
# Main
#
# Argument has been provided
if [[ $# -gt 0 ]]; then
# Check that all the arguments are the valid path
find "$@" -exec bash -c '
for filepath do
if [[ ! -e "$filepath" ]]; then
echo_error_not_found "$filepath"
exit 2
fi
done
' sh {} +
if [[ $? -eq 0 ]]; then
find_exec "$@"; fi
# No arguments provided.
else
find_exec .
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment