I am trying to create a bash-based inventory scanner, and was wondering if there is anything 'glaringly' incorrect about my syntax or usage. I was hoping I could get some feedback on: - bash programming best practice in regards to syntax, modularity, variable passing - Maybe some book suggestions? - How can I do it right the first time so I don't have to refactor later? - Best way to interface MySQL with bash - Suggestions on debugging (`bash -x` AND `printf`?) Future plans: Implement a barcode printer and various other functions to manipulate the warehouse inventory....the reason why I am writing this, is because we are currently keeping track of inventory (a few thousand items) using spreadsheets, and meat-based memory. Also might throw it onto a raspi, with a buck converter, battery pack, LCD screen, and WiFi dongle. The first stab: #!/bin/bash # [email protected] 2014 # use it however if you find it useful # Bash based inventory system # This is a very simple utility for updating # MySQL information for item location in a DB # in a warehouse of inventory system ################################################# PASS=$1 ############################################# locationlist=( 'MA1' 'MA2' 'MA3' 'MA4' 'MA5' 'MA6' 'MA7' 'MA8' 'MB1' 'MB2' 'MB3' 'MB4' 'MB5' 'MB6' 'MB7' 'MB8' ) scanmodelist=( 'relocate_item' 'relocate_bin' 'set_item_status' ) pretenditems=( '123' '456' ) mysqlhost="localhost" mysqluser="root" DBNAME="test" ############################################# printf "################################ starting ####################\n" #echo ${scanmodelist[@]} ${locationlist[@]} ${pretenditems[@]} if [[ -z $PASS ]]; then read -s -p 'Please [enter] SQL user password:' PASS fi set_scanmode () { input=$1 if [ $input == 'relocate_item' ];then relocate_item elif [ $input == 'relocate_bin' ];then relocate_bin fi echo 'done' $input } return_scanner_input () { read -p 'scan:' -e input echo $input } check_input_for_scanmode () { for mode in ${scanmodelist[@]} do if [[ $mode == $1 ]] then mode=$1 # requires: $sku $location break else mode='' fi done echo $mode } check_input_for_location () { _location=$1 for item in ${locationlist[@]} do ##printf "[INFO]:check_input_for_location:Comparing: $location With: $item \n" if [ $item == $_location ] then ##printf "[INFO]:check_input_for_location:FOUNDL:$item \n" location=$item ##printf "[INFO]:check_input_for_location:breaking location \n" break else ##printf "[INFO]:check_input_for_location:NOFOUNDL:$item \n" location='' fi done ##printf "[INFO]:check_input_for_location: location:$location \n" echo $location } set_item_status () { echo $sku print_sql_row_from_sku $sku } relocate_item () { while true; do clear # check if mode and location are none # for first scan if [[ -z $mode ]]; then input=$(return_scanner_input) mode=$(check_input_for_scanmode $input) elif [[ -z $location ]]; then printf "Which location?\n" input=$(return_scanner_input) location=$(check_input_for_location $input) continue fi printf "Location:$location\n" printf "Which sku?\n" # if location and mode then grab sku input=$(return_scanner_input) sku=$(check_input_sku_exists $input) # check if sku if [[ -n $sku ]]; then #printf "[INFO]:relocate_item: if -n sku: sku:$sku \n" # else check if input is else _location=$(check_input_for_location $input) _mode=$(check_input_for_scanmode $input) #printf "[INFO]:relocate_item: else: _location:$_location \n" #printf "[INFO]:relocate_item: else: _mode:$_mode \n" if [[ -n $_mode ]]; then run elif [[ -n $_location ]]; then location=$_location printf "Switched Location:$location\n" else printf "I didnt find that sku.\n" fi sleep 1 continue fi if [[ -z $sku ]]; then exit fi #printf "[INFO]:relocate_item: 1: sku:$sku location:$location \n" print_sql_row_from_sku $sku #printf "[INFO]:relocate_item: 2: sku:$sku location:$location \n" update_item_location $sku $location #printf "[INFO]:relocate_item: 3: sku:$sku location:$location \n" print_sql_row_from_sku $sku #printf "[INFO]:relocate_item: 4: sku:$sku location:$location \n" generate_zint_bar_code $sku sleep 1 done } relocate_bin () { printf '\nrelocate_bin()\n' } update_item_location () { # requires: $sku $location #printf "[INFO]update_item_location: sku:$1 location:$2 \n" mysql -h$mysqlhost -u$mysqluser -p$PASS $DBNAME <<EOF UPDATE item SET location="$2" WHERE sku="$1"; EOF sleep 5 } check_input_sku_exists () { # run mysql check here # requires: $sku _sku=$1 #printf "\n##############\n[INFO]:check_input_sku_exists:_sku:$_sku \n" if [[ -n $( mysql -h$mysqlhost -u $mysqluser -p$PASS $DBNAME <<EOF SELECT * FROM item WHERE sku="$_sku"; EOF ) ]] then #printf "\n######\n[INFO]:check_input_sku_exists:_sku: IF true: $_sku \n\n" echo $_sku else ##printf "[INFO]:check_input_sku_exists:_sku: IF false: $_sku \n\n" echo '' fi } print_sql_row_from_sku () { # requires: $sku #printf "[INFO]:print_sql_row_from_sku:Printing row\n" mysql -h$mysqlhost -u$mysqluser -p$PASS $DBNAME <<EOF SELECT * FROM item WHERE sku="$1"; EOF sleep 1 } create_item () { printf "\ntrying to insert item: $1\n" status="pending" #sku | title | jnumber | state | load_id | bin_location | msrp | condition_id | band_size | date_listed | upc mysql -h$mysqlhost -u$mysqluser -p$PASS $DBNAME <<EOF INSERT INTO item VALUES ('$1',NULL,NULL,'$status',NULL,NULL,NULL,NULL,NULL,NULL,NULL); EOF mysql -h $mysqlhost -u $mysqluser -p$PASS -e "use $DBNAME;DESCRIBE item;" mysql -h $mysqlhost -u $mysqluser -p$PASS -e "USE $DBNAME;SELECT * FROM item LIMIT 100" printf '\nalso im making a bar code\n' } generate_zint_bar_code () { # requires: $sku mkdir -p ./tmp zint -o ./tmp/$1.png -d $1 } run () { # uncomment these to test # test_data # exit # clear location='' scanmode='' input='' sku='' mode='' printf 'running...\n' read -p 'set_scanmode:' -e mode set_scanmode $mode } test_data () { sku="example-sky-0123" location="MB1" print_sql_row_from_sku $sku results=$(update_item_location $sku $location) echo $results results=$(check_input_sku_exists $sku) echo $results } run #!/bin/bash #PASS='password' #mysql -h localhost -u root -p$PASS -e "create database test" #mysql -h localhost -u root -p$PASS -e "use test;SHOW tables;" #mysql -h localhost -u root -p$PASS -e "use test;create table item (state char(25))" #mysql -h localhost -u root -p$PASS -e "use test;ALTER TABLE item ADD state char(25))" #mysql -h localhost -u root -p$PASS -e "use test;ALTER TABLE item ADD (state char(25))" #mysql -h localhost -u root -p$PASS -e "use test;SHOW tables;" #mysql -h localhost -u root -p$PASS -e "use test;DESCRIBE item;" #mysql -h localhost -u root -p$PASS -e "use test;INSERT INTO item;VALUES ('the_sku','a title','a jnumber','pending')" #mysql -h localhost -u root -p$PASS -e "use test;INSERT INTO item VALUES ('the_sku','a title','a jnumber','pending')" #mysql -h localhost -u root -p$PASS -e "use test;DESCRIBE item;" #mysql -h localhost -u root -p$PASS -e "use test;SHOW tables;" #mysql -h localhost -u root -p$PASS -e "SELECT item FROM test LIMIT 2" #mysql -h localhost -u root -p$PASS -e "USE test;SELECT * FROM item LIMIT 2" Images/Barcode example and other info on [GitHub][1]. [1]: https://github.com/jmunsch/bash_inventory_scanner