1
\$\begingroup\$

I just finished creating my first bash script that helps me to launch documents from terminal using a pdf viewer. This is very helpful and fast (at least I think so) for people who don't use any files manager (and have lots of documents of course); therefore they launch their pdf viewer and documents from terminal.

I wish to upload the script on Github so any feedback, review, or tip on how it is or how to improve it before the upload is really appreciated.

Here is the script:

rdoc

#!/bin/env bash
declare -r CONF_DIR_PATH=~/.config/rdoc
declare -r CONF_DOC_DIR=$CONF_DIR_PATH/doc_dir
declare -r CONF_PDF_VIEWER=$CONF_DIR_PATH/pdf_viewer
declare -r TMP_FILE=/tmp/.rdoc_tmp
fn_generate_configs() {
 local doc_dir_path
 local pdf_viewer_name
 mkdir -p $CONF_DIR_PATH
 
 echo -n "Please enter your documents directorie's full path: "
 read doc_dir_path
 echo $doc_dir_path > $CONF_DOC_DIR
 echo -ne "\nPlease enter your pdf's viewer name: "
 read pdf_viewer_name
 echo $pdf_viewer_name > $CONF_PDF_VIEWER
 echo 
 echo Your configurations were generated succesfully.
}
fn_read_configs() {
 doc_dir=$(cat $CONF_DOC_DIR 2> /dev/null)
 if [ ! $? -eq 0 ]; then 
 echo Error: one or all of your configuration files are missing.
 echo Try -h for help.
 exit -1
 fi
 pdf_viewer=$(cat $CONF_PDF_VIEWER 2> /dev/null) 
 if [ ! $? -eq 0 ]; then
 echo Error: one or all of your configuration files are missing.
 echo Try -h for help.
 exit -1
 fi
}
fn_search_for_book() {
 local path
 local grep_opt=""
 local string_to_exclude=1ドル/
 
 if [ $i_status -eq 1 ]; then 
 grep_opt=-i
 fi
 if [ $r_status -eq 1 ]; then #Search recursively 
 for path in 1ドル/*; do 
 if [ -d $path ]; then 
 fn_search_for_book $path
 elif [ -f $path ]; then 
 if echo $path | grep -q $grep_opt $book_name; then 
 echo $path | sed "s|$string_to_exclude||" >> $TMP_FILE
 fi
 fi
 done
 else
 for path in 1ドル/*; do
 if [ -f $path ]; then 
 if echo $path | grep -q $grep_opt $book_name; then 
 echo $path | sed "s|$string_to_exclude||" >> $TMP_FILE
 fi
 fi
 done
 fi
}
fn_display_books() {
 local doc
 local founded_docs
 
 #Make sure a book was founded and TMP_FILE was generated
 founded_docs=$(cat $TMP_FILE 2> /dev/null)
 if [ ! $? -eq 0 ]; then 
 echo Error: no document was found with \'$book_name\' in it.
 exit -1
 fi
 echo -e "These are the documents that were found:\n"
 #Set output's color to red
 tput setaf 1
 
 for doc in $founded_docs; do 
 echo $doc
 done
 #Reset output's color 
 tput sgr0 
}
fn_count_books() {
 local doc
 local cnt=0
 local founded_docs
 founded_docs=$(cat $TMP_FILE 2> /dev/null)
 if [ ! $? -eq 0 ]; then
 echo Error: \'$TMP_FILE\' manipulation while the program is running are disallowed.
 exit -1
 fi
 
 for doc in $founded_docs; do 
 (( cnt++ ))
 done
 return $cnt
}
fn_final_book_name() {
 echo -ne "\nWhich one of them would you like to open: "
 read book_name
}
fn_generate_books_paths() {
 local path
 
 if [ $r_status -eq 1 ]; then
 for path in 1ドル/*; do
 if [ -d $path ]; then
 fn_generate_books_paths $path
 elif [ -f $path ]; then
 echo $path >> $TMP_FILE
 fi
 done
 else 
 for path in 1ドル/*; do
 if [ -f $path ]; then
 echo $path >> $TMP_FILE
 fi
 done
 fi
}
fn_get_book_path() {
 local founded_paths
 local path
 local grep_opt=""
 founded_paths=$(cat $TMP_FILE 2> /dev/null)
 if [ ! $? -eq 0 ]; then
 echo Error: \'$TMP_FILE\' manipulation while the program is running are disallowed.
 exit -1
 fi
 if [ $i_status -eq 1 ]; then
 grep_opt=-i
 fi
 for path in $founded_paths; do 
 if ! echo $path | grep -q $grep_opt $book_name; then 
 continue
 fi
 book_path=${path}
 break
 done
}
fn_open_book() {
 $pdf_viewer $book_path 2> /dev/null
 if [ ! $? -eq 0 ]; then 
 echo 
 echo Error: \'$book_path\' can\'t be opened. 
 exit -1
 fi
 echo -e "\nOpening: $book_path"
}
fn_help_message() {
 echo Usage: rdoc \<options\> [argument]
 echo 
 echo Available options:
 echo " -h Display this help message. "
 echo " -g Generate new configuration files. "
 echo " -r Allow recursive searching for the document. "
 echo " -i Ignore case distinctions while searching for the document. "
 echo " -s Search for the document and display results. " 
 echo " This option takes a document name or a part of it as an argument. "
 echo " -o Search for the document, display results then open it using your pdf viewer. "
 echo " This option takes a document name or a part of it as an argument. "
 echo " (Default) "
 echo "NOTE: "
 echo " When using '-s' or '-o' option in a combination of other options like this: "
 echo " "
 echo " $ rdoc -ris document_name "
 echo " "
 echo " Please make sure that it's the last option; to avoid unexpected behaviour. " 
}
doc_dir=""
pdf_viewer=""
book_path=""
book_name=${BASH_ARGV[0]} #book_name equals to the last arg by defualt so the default option ('-o') will work.
#Options status
r_status=0
i_status=0
s_status=0
o_status=1 #Make -o the default option 
#Display help message if no options were passed 
if [ $# -eq 0 ]; then
 fn_help_message
 exit 0
fi
while getopts ":hgris:o:" opt; do
 case $opt in 
 h)
 fn_help_message
 exit 0
 ;;
 g)
 fn_generate_configs
 o_status=0
 ;;
 r)
 r_status=1
 ;;
 i)
 i_status=1
 ;;
 s)
 book_name=$OPTARG
 s_status=1
 o_status=0 
 ;;
 o)
 book_name=$OPTARG
 ;;
 :)
 echo Error: an argument is required for \'-$OPTARG\' option.
 echo Try -h for help.
 exit -1
 ;;
 *)
 echo Error: unknown option \'-$OPTARG\'.
 echo Try -h for help.
 exit -1
 ;;
 esac
done
if [ $s_status -eq 1 ] || [ $o_status -eq 1 ]; then 
 #Make sure there isn't $TMP_FILE already generated from previous runs.
 rm $TMP_FILE 2> /dev/null
 fn_read_configs
fi
if [ $s_status -eq 1 ]; then
 fn_search_for_book $doc_dir
 fn_display_books
elif [ $o_status -eq 1 ]; then 
 fn_search_for_book $doc_dir
 fn_display_books
 fn_count_books
 if [ $? -gt 1 ]; then #If more than 1 book were found with $book_name in it
 fn_final_book_name
 #Clean any leftovers of $TMP_FILE to search properly
 rm $TMP_FILE 2> /dev/null
 #Make sure that the user chose an available document
 fn_search_for_book $doc_dir
 if [ ! -f $TMP_FILE ]; then 
 echo 
 echo Error: no document was found with \'$book_name\' in it.
 exit -1
 fi
 #Make sure that the user is specific enough about the book name
 fn_count_books
 if [ $? -gt 1 ]; then
 echo
 echo Error: More than 1 book was found with the name \'$book_name\' in it.
 exit -1
 fi
 fi
 
 echo -n "" > $TMP_FILE #Make sure $TMP_FILE is empty so it'll be usable in fn_generate_books_paths
 fn_generate_books_paths $doc_dir
 fn_get_book_path
 fn_open_book
fi
exit 0

Thanks for your time guys.

asked May 6, 2021 at 12:22
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

#!/bin/env bash

Prefer #!/usr/bin/env bash


CONF_DOC_DIR and CONF_PDF_VIEWER can be removed and use $CONF_DIR_PATH/config with contents:

CONF_DOC_DIR=...
CONF_PDF_VIEWER=...

Reading the config would become: source $CONF_DIR_PATH/config


TMP_FILE should be generated with mktemp so that we are guaranteed that file does not already exist


mkdir -p $CONF_DIR_PATH

If value of CONF_DIR_PATH has one or more spaces, then multiple directories would be created. Quote the variable to prevent splitting: mkdir -p "$CONF_DIR_PATH"


echo -n "Please enter your documents directorie's full path: "

Typo: directories


fn_ prefix for function names is not necessary


for path in 1ドル/*; do

Prefer find -type f -exec ...


echo Error: no document was found with '$book_name' in it.

Quote escaping can be avoided with echo "Error: no document was found with '$book_name' in it. "

answered May 8, 2021 at 4:50
\$\endgroup\$
1
  • \$\begingroup\$ Thank you for the review, I'll fix everything of course and I really appreciate it. \$\endgroup\$ Commented May 8, 2021 at 10: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.