LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Help with rsync file restore script (https://www.linuxquestions.org/questions/linux-newbie-8/help-with-rsync-file-restore-script-4175441161/)

jdavis_33 12-12-2012 12:31 PM

Help with rsync file restore script
 
Code:

#!/bin/bash
#
# Partial Rsync File Restore Script
#
#
clear
echo
# Shell loads into /raid0/data/backup/bin/
cd ..              # I cd to the backup directory here 
cd store/          # Then cd into store/ here, which is where the script should run       
echo "You are here>  `pwd`"     
echo
echo "Please select a directory or file to restore"
echo
select file in `for i in $(ls); do echo ${i%%.*}; done`
  do
  echo; echo "$file"
  break;
  done
if [ -d "$file" ]
 then
  cd $file; pwd
else
  echo "Restore $file?"
fi
unset file   

select file in `ls`; do echo "$file"; break; done
if [ -d "$file" ]
 then
  cd $file
else
  echo "Restore $file?"
fi
unset file

select file in `ls`; do echo "$file"; break; done
if [ -d "$file" ]
 then
  cd $file
else
  echo "Restore $file?"
fi
unset file

The problem I am having is with the select and if commands. Can I create some kind of loop to accomplish this without having to recreate the code manually everytime.

Thanks for your help.

unSpawn 12-12-2012 04:19 PM

Quote:

Originally Posted by jdavis_33 (Post 4847861)
Can I create some kind of loop to accomplish this without having to recreate the code manually everytime.

If you put your selection menu in a function:
Code:

doSomething() { select SELECTION in $(find $PWD -maxdepth 1 -printf "\"%f\"\n"); do doSomethingElse; done; }
then each time the function is executed it will refresh the selection list. If you put your file ops in a function too:
Code:

doSomethingElse() { if [ -d "${SELECTION}" ]; then cd "${SELECTION}" && doSomething
 elif [ -f "${SELECTION}" ]; then echo "Restore $file? [y/N]"; else cd .. || doSomething; fi; }

then having the first function execute the second one and vice versa you'll create a loop that always does something. (Start by executing the doSomething function)
* Note 0) due how to "select" works in your code as well as in this example the 'find' and 'ls' commands return IFS-unsafe results, resulting in multiple menu entries for what are single items, also note 1) your menu doesn't distinguish directory names (to enter) from file names and 2) your approach may work well with a single directory holding 2 or 3 files but not with a directory holding 100 directories and 1 file or 2000 directories plus subdirectories.

jdavis_33 12-12-2012 04:29 PM

Thanks @unSpawn, your insight has been most helpful.

jdavis_33 12-18-2012 06:11 PM

@unSpawn, I still haven't found a way around using 'ls' or 'find'. I know that they return unsafe IFS results and that it results in some files having multiple menu entries. I am still looking for a way to combat that issue. However, I have improvised my code and would like to have you look at it for me. Below you will see my new code. Please note that I have additional problems that I now need to resolve. I am hoping that you can help me with these. I will explain them below. Please also note that the script is still incomplete.

Thanks


Code:

#!/bin/bash
#=========================================================================================================
# Rsync File Restore Script [Unfinished]                  ********************************************* #
# This script is in /raid0/data/backup/                    *                                          * #
#                                                          * Author: Johnny J. Davis                  * #
#                                                          * Date Created:                            * #
# [ Last Modified ]                                        * Script name: filerestore_take2.sh        * #
# Date:                    12/18/12                        *            [incomplete]                  * #
# Time:                    9:32 AM                        *                                          * #
#                                                          ********************************************* #                                         
##########################################################################################################

#=========================================================================================================
#                                      ****[Begin Variables]****
#=========================================================================================================
LogDns1=/raid0/data/backup/logs/dns1_file_restore.log
LogServices=/raid0/data/backup/logs/services_file_restore.log
LogInet1=/raid0/data/backup/logs/inet1_file_restore.log
LogUser=/raid0/data/backup/logs/UserLog.log
NoLog="echo No log present for $secondhalf"            # The variable $secondhalf will be assigned later
RSYNC=/usr/bin/rsync                                    # on as a result of user input.
DATE=/bin/date
ECHO=/bin/echo
USER=root
#---------------------------------------------------------------------------------------------------------
# {End Variables}
#=========================================================================================================
#                                      ****[Begin Functions]****
#=========================================================================================================
# Function to remove previous log, if present (DNS1)
removeLogDns1(){
if [ -a $LogDns1 ]
  then
    rm $LogDns1
  else
    echo "No log present for Dns1!"
fi
}
# Function to remove previous log, if present (SERVICES)
removeLogServices(){
if [ -a $LogServices ]
  then
    rm $LogServices
  else
    echo "No log present for Services!"
fi
}
# Function to remove previous log, if present (INET1)
removeLogInet1(){
if [ -a $LogInet1 ]
  then
    rm $LogInet1
  else
    echo "No log present for Inet1!"
fi
}       
#-------------------------------------------------------------(Step 6)------------------------------------
# Function that confirms the intention to restore and restores the file 
# placed in the variable fileName by the fileCheck function in step 3.
restoreFile(){
echo -n "Restore $fileName? [Y/N]?> "
read -r answer
 case $answer in
      Y ) echo "Restoring the file $fileName!"                  # Will be Adding additional commands here
          ;;
      N ) echo "Action aborted, nothing restored!"; makeSelection
          ;;
      * ) echo "Must answer with a Y or N!"
          ;;
 esac
#exit 0; sh /raid0/data/backup/filerestore_take2.sh
}
#-------------------------------------------------------------(Step 5a)---------------------------
# Function that changes the current working directory to the choice made in step 2, if infact
# it was a directory.
cdNow(){
if [ -d $choice ]
 then
  cd $choice; echo "Changed Directory to $PWD"; makeSelection
 else                                                  # If the choice from step 2 is not a directory and
  echo "This is not a directory!"                    # manages to make it to this step, the script will   
fi                                                    # terminate with echo.
}
#-------------------------------------------------------------(Step 5b)---------------------------
# Function checks to see if the choice from step 2, is infact a file. If so, it stores the file
# name in a variable called fileName and proceeds to call the restoreFile function in step 4.
fileCheck(){
if [ -f $choice ]
 then
  fileName=$choice; restoreFile
 else                                                        # If the choice from step 2 is not a file
  echo "This is not a file!"                                # and manages to make it to this step, the
fi                                                            # script will terminate with echo.

#-----------------------------------------------------------(Step 4)--------------------------------------
# Function that determines if the selection from step 1 is a file
# or directory and moves to next function based on the result.
checkType(){
while [ -d $choice ]                                  # Checks the variable to see if it is a directory.
  do                                                  # If so, it calls the cdNow function, in step 5a.
  cdNow
  break;
  done
 
while [ -f $choice ]                                  # Checks the variable to see if it is a file. If so,
  do                                                  # it calls the fileCheck function, in step 5b.
  fileCheck
  break;
  done
}
#------------------------------------------------------------(Step 3)-------------------------------------
# Function checks for existance of files.
anyFiles(){ 
ls ./* > /dev/null 2>&1
  if [ "$?" = "0" ]
  then
    checkType
  else
    echo "No files exist here!"
  fi
}
#------------------------------------------------------------(Step 2)-------------------------------------
# Fuction that allows selecting either a file or directory.
makeSelection(){
PS3="Enter choice [ctrl-c quits]> "
select choice in `for i in $(ls -X); do echo ${i%%.*}; done` 
 do echo; break; done
anyFiles
}
#---------------------------------------------------------------------------------------------------------
# {End Functions}
#=========================================================================================================
#                                    ****[Script Start]****  (Step 1)
#=========================================================================================================
#
echo
echo
echo
clear
echo "Current Working Directory: $PWD"     
echo
echo "Please select file or directory."
echo
echo "[Selecton Menu]"
makeSelection


Upon execution of the script, I get some prompts duplicated after performing the task. For instance, after traversing several directories, to finally reach the file that I would like to restore. I am prompted to restore the file. I say yes to restore. I get the echo stating that the file is being restored, then immediately after, I get the same prompt. I know it's something in the functions causing this, but I don't know how to resolve it. Also, while entering a selection at the selection menu, I deliberately entered an invalid choice to see what would happen. It drops to /root and echos "No files exist here!" and prompts to Restore ? [Y/N]?>. I don't know what's causing this or how to fix it. Do you have any ideas about any of this?

Thanks

jdavis_33 12-18-2012 06:16 PM

I should also point out that I am working on a Thecus N4100Pro Nas via ssh. The box has a very limited command set, as it is running a dumbed-down version of Slackware. Some options for the commands that do exist, are non-existent on this box. For instance, 'find' with the -maxdepth or -mindepth options. Find is a valid command for the box, but the options do not exist.

unSpawn 02-26-2013 08:08 AM

Quote:

Originally Posted by jdavis_33 (Post 4852266)
I still haven't found a way around using 'ls' or 'find'. (..) Upon execution of the script, I get some prompts duplicated after performing the task. For instance, after traversing several directories, to finally reach the file that I would like to restore. I am prompted to restore the file. I say yes to restore. I get the echo stating that the file is being restored, then immediately after, I get the same prompt. I know it's something in the functions causing this, but I don't know how to resolve it. Also, while entering a selection at the selection menu, I deliberately entered an invalid choice to see what would happen. It drops to /root and echos "No files exist here!" and prompts to Restore ? [Y/N]?>. I don't know what's causing this or how to fix it. Do you have any ideas about any of this?

The easiest way to trace shell script problems is to enable verbose / debug mode with a "#!/bin/bash -vx" hashbang or setting "set -vx" below the shebang line. Then run the script piping stderr + stdout through 'tee' to a log file, and perform one task only, for example selecting a non-existent file to restore, and then exit the script. Then read back the log file to see what variables get assigned (or not) and what functions get called and in what order. Tedious to some it gives you the level of insight you need to fix this. Try it and if you've got questions attach your log file as plain text. Wrt the NAS it would be interesting to know if it actually runs slackware user land (and what BASH version) or Busybox. In case of the latter I suggest you install a copy of the Heirloom Shell (@Sourceforge IIRC) which I use for Bourne-compatible scripting.


All times are GMT -5. The time now is 08:24 PM.