2
\$\begingroup\$

I've started bash scripting recently and currently I'm working on a program that simplifies backuping using rsync . I'd appreciate any feedback on what I've done wrong / what can be improved.

#!/bin/bash
# Copyright (C) 2020 ##########, e-mail: ##################
# saver comes with NO WARRANTY. This program is completely free and you can
# redistribute it under the GNU General Public License conditions.
# See https://www.gnu.org/licenses/gpl-3.0.txt for more information
# saver was made to simplify the process of backuping using rsync.
# version 2.2-1
if [[ ! $(id -u) == 0 ]]; then # making sure the progream is executed as root
 exec sudo 0ドル "$@"
fi
for ((i=1; i=i; i++)); do # here input variables of the script are read one by another using the for loop
 [[ -z ${!i} ]] && break
 case ${!i} in
 \-*) # this is where all the '-' options are
 case ${!i} in
 *s*) option=$option"sync" ;;& 
 *d*) rsyncoptions+=(-n) ;;& 
 *r*) rsyncoptions+=(--delete) ;;&
 *p*) rsyncoptions+=(--progress) ;;&
 *v*) rsyncoptions+=(-v) ;;&
 *h*) option=$option"help" ;;&
 *i*) option=$option"diskinfo" ;;
 esac
 ;;
 *) # here the paths and disks are set
 if [[ -b ${!i} ]]; then
 if [[ -z $sp ]]; then
 sdp="${!i}"
 else
 tdp="${!i}"
 fi
 else
 if [[ -b /dev/${!i} ]]; then
 if [[ -z $sp ]]; then
 sdp="/dev/${!i}" # sdp = sync disk path
 else
 tdp="/dev/${!i}" # tdp = target disk path
 fi
 else
 if [[ ${!i} == /* ]]; then 
 if [[ -z $sp ]]; then
 sp="${!i}" # sp = sync path
 else
 tp="${!i}" # tp = target path
 fi
 fi
 fi
 fi
 ;;
 esac
done
case $option in
 sync) # the -s option
 if [[ ! -e $sp ]]; then # checking if the path to sync from exists
 echo -e "The path to copy wasn't provided or doesn't exist\nType in 'saver -h' to see the list of commands"
 logger "saver: The path to copy wasn't provided or doesn't exist"
 exit
 fi
 if [[ -z $tp ]]; then # checking if the target path isn't empty
 echo -e "The target path wasn't provided\nType in 'saver -h' to see the list of commands"
 logger "saver: The target path wasn't provided"
 exit
 fi
 fsp=$sp # these stand for the final paths that will be put to the rsync command (final sync path / final target path)
 ftp=$tp
 if [[ $sdp ]]; then 
 echo "Unmounting the disk to copy"
 umount -q $sdp # mounting the sync external disk to a folder that's made
 
 echo "Creating /mnt/saverbd"
 mkdir /mnt/saverbd | grep -q a
 
 echo -e "Mounting the disk to copy to /mnt/saverbd\n"
 mount $sdp /mnt/saverbd 
 
 fsp=/mnt/saverbd${sp} # updates the final path if it's from an external disk
 fi
 if [[ $tdp ]]; then
 echo "Unmounting the target disk"
 umount -q $tdp # mounting the target external disk to a folder that's made
 echo "Creating /mnt/savertd"
 mkdir /mnt/savertd | grep -q a
 echo -e "Mounting the target disk to /mnt/savertd\n"
 mount $tdp /mnt/savertd
 ftp=/mnt/savertd${tp} # updates the final path if it's from an external disk
 fi
 if [[ ! -e $tp ]]; then
 echo "Creating ${ftp}"
 mkdir -p $ftp | grep -q a 
 fi
 echo
 rsync -aAX "${rsyncoptions[@]}" $fsp --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} $ftp
 if [[ $sdp ]]; then # unmounting the sync external disk and deleting the mount folder
 echo -e "\nUnmounting the copied disk"
 umount -q $sdp
 echo -e "Deleting /mnt/saverbd\n"
 rm -rf /mnt/saverbd
 fi
 if [[ $tdp ]]; then # unmounting the target external disk and deleting the mount folder
 echo -e "\nUnmounting the target disk"
 umount -q $tdp
 
 echo -e "Deleting /mnt/savertd\n"
 rm -rf /mnt/savertd 
 
 fi
 ;;
 diskinfo)
 lsblk -o NAME,SIZE,MOUNTPOINT,FSTYPE # shows the available disks and partitions
 ;;
 help) # the help page
 echo -e "\n Copyright (C) 2020 ###########, e-mail: ##################
 Version 2.2-1
\n saver comes with NO WARRANTY. This program is completely free and you\n can redistribute it under the GNU General Public License conditions.\n See https://www.gnu.org/licenses/gpl-3.0.txt for more information
\n saver was made to simplify the process of backuping using rsync.
\n This program will automaticly exclude these directories from syncing:\n /dev ; /proc ; /sys ; /tmp ; /run ; /mnt ; /media ; /lost+found.
 When typing in the disk name, you can use the full '/dev/(disk)' or just\n provide the name of the disk.
 Any disk you mention will be unmounted at the end of the program.
\n Usage:
\n -s [disk to copy (empty for current disk)] [copied path]\n [target disk (empty for current disk)] [target path]
\n Options:
\n -s Sync folders
 -r Delete any other files in the target folder
 -d Preform a 'dry run', no changes will be made
 -p Display progress for individual files (useful for large files)
 -v Display files that are being processed
 -i Show available disks/partitions
 -h Show this help\n"
 ;;
 *) # in case no valid option is provided
 echo -e "Invalid option provided\nType in 'saver -h' to see the list of commands"
 logger saver: "Invalid option provided" 
 ;;
esac
asked Jul 1, 2020 at 10:14
\$\endgroup\$
4
  • 1
    \$\begingroup\$ It does, what I mean by that is if the code I've written can be somehow optimized, if there can be any compatibility issues. I'm new to bash scripting so I tend to make mistakes. \$\endgroup\$ Commented Jul 1, 2020 at 11:12
  • 2
    \$\begingroup\$ Welcome to Code Review. To increase the odds of receiving answers about your script, it could be better to modify the title of you post to include a brief description of the task implemented by the script. \$\endgroup\$ Commented Jul 1, 2020 at 12:41
  • 1
    \$\begingroup\$ As @dariosicily indicated a better title might be bash backup script. \$\endgroup\$ Commented Jul 1, 2020 at 13:09
  • \$\begingroup\$ I changed the title, but "bash backup script" was taken. \$\endgroup\$ Commented Jul 1, 2020 at 13:22

1 Answer 1

2
\$\begingroup\$

loop

for ((i=1; i=i; i++)); do 
 [[ -z ${!i} ]] && break

you know that $# hold number of argument from command line ?

you can use

for ((i=1; i <= $# ; i++)) 

test

if [[ ! $(id -u) == 0 ]]

you know about != ? use

if [[ $(id -u) != 0 ]]

mkdir

what is the purpose of .. ?

mkdir /mnt/savertd | grep -q a

Do you want to get rid of "mkdir: cannot create directory ‘/mnt/savertd’: File exists" message ?

this won't work (message is printed on stderr, while | will collect stdout), use either

test -d /mnt/savertd || mkdir /mnt/savertd

or

mkdir -p /mnt/savertd
  • second form is better, it will create all directory along the path, first one will fail if /mnt do not exists.
  • mkdir -p will also not complain if directory exists.

echo -e

you have some

echo -e "Mounting the target disk to /mnt/savertd\n"

(削除) why use both -e (no new line) and a trailling \n (new line) ? (削除ここまで)

actually :

  • -e enable interpretation of backslash escapes

long echo -e in help section can be replaced by a here documentation

cat <<EOF
 Copyright (C) 2020 ###########, e-mail: ##################
 Version 2.2-1
 saver comes with NO WARRANTY. This program is completely free and you
 can redistribute it under the GNU General Public License conditions.
 See https://www.gnu.org/licenses/gpl-3.0.txt for more information
 saver was made to simplify the process of backuping using rsync.
 This program will automaticly exclude these directories from syncing:
 /dev ; /proc ; /sys ; /tmp ; /run ; /mnt ; /media ; /lost+found.
 When typing in the disk name, you can use the full '/dev/(disk)' or just provide the name of the disk.
 Any disk you mention will be unmounted at the end of the program.
 Usage:
 -s [disk to copy (empty for current disk)] [copied path]
 [target disk (empty for current disk)] [target path]
 Options:
 -s Sync folders
 -r Delete any other files in the target folder
 -d Preform a 'dry run', no changes will be made
 -p Display progress for individual files (useful for large files)
 -v Display files that are being processed
 -i Show available disks/partitions
 -h Show this help
EOF
answered Jul 1, 2020 at 11:59
\$\endgroup\$
3
  • \$\begingroup\$ Thanks a lot I've heard about $#, but after I wrote that code so I haven't thought about that. All the other tips are really helpful too. I also wasn't sure how to use a here document, so I used a long echo, but this is much cleaner. Thanks again. \$\endgroup\$ Commented Jul 1, 2020 at 12:49
  • \$\begingroup\$ I'm not sure about what you said of echo -e with \n . echo -e doesn't block a new line. echo -n does that. I used 'echo -e' with '\n' to have two new lines. \$\endgroup\$ Commented Jul 1, 2020 at 13:06
  • \$\begingroup\$ yes my fault, -e enable interpretation of backslash escapes \$\endgroup\$ Commented Jul 1, 2020 at 13:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.