Bash Script to create another file - bash

I created a simple shell script:
#!/bin/bash
clear
echo "Starting Script now....."
echo "Write the info below to a new file in same directory...."
echo "name: John Smith"
echo "email: jsmith#demo.com
echo "gender: M"
echo
echo
echo "File is done"
I want to create a file in the same directory with the Name, email, and gender details.
I don't want to do it from the command line like this:
#./script.sh > my.config
I'd rather do it from within the file itself.

Heredoc.
cat > somefile << EOF
name: ...
...
EOF

You can just do:
#!/bin/bash
clear
echo "Starting Script now....."
echo "Write the info below to a new file in same directory...."
# save stdout to fd 3; redirect fd 1 to my.config
exec 3>&1 >my.config
echo "name: John Smith"
echo "email: jsmith#demo.com"
echo "gender: M"
echo
echo
# restore original stdout to fd 1
exec >&3-
echo "File is done"

Well, just add >> yourfile to the echo lines you want to write :
echo "name: John Smith" >> yourfile
echo "email: jsmith#demo.com" >> yourfile
echo "gender: M" >> yourfile

For all your echo "name:John Smith" lines add a > $1 (ie first parameter passed in to the script).
Then run the script like ./script.sh my.config.
Or you could replace the $1 with my.config and just run ./script.sh.

Related

Handling logs of bash script and comments in text file

I am trying to read a text file which has few commented starts with '#', my bash script should read the lines of the text file which doesn't start with '#'.
Also im trying to capture the output of echo statements in both logs and to show it console window for the user understanding.
I have tried to use the below query for capturing logs and printing in console
exec 2>&1 1>>$logfile
For reading each line of the file and calling the function, i have declared an array and to eliminate lines which starts with '#' , i have used the below query.
declare -a cmd_array
while read -r -a cmd_array | grep -vE '^(\s*$|#)'
do
"${cmd_array[#]}"
done < "$text_file"
Note : I need to eliminate the line starts with '#' and remaining lines to be read and place in array as declared.
Bash script
***********
#! /bin/bash
Function_1()
{
now=$( date '+%Y%m%d%H%M' )
eval logfile="$1"_"$now".log
exec 2>&1 1>>$logfile ### Capture echo output in log and printing in console
#exec 3>&1 1>>$logfile 2>&1
echo " "
echo "############################"
echo "Function execution Begins"
echo "############################"
echo "Log file got created with file name as $1.log"
eval number=$1
eval path=$2
echo "number= $number"
ls -lR $path >> temp.txt
if [ $? -eq 0 ]; then
echo " Above query executed."
else
echo "Query execution failed"
fi
echo "############################"
echo "Function execution Ends"
echo "############################"
echo " "
}
text_file=$1
echo $text_file
declare -a cmd_array ### declaring a array
while read -r -a cmd_array | grep -vE '^(\s*$|#)' ### Read each line in the file with doesnt starts with '#' & keep it in array
do
"${cmd_array[#]}"
done < "$text_file"
Text file
*********
####################################
#Test
#Line2
####################################
Function_1 '125' '' ''
Function_1 '123' '' ''
Consider piping the grep output into the read:
declare -a cmd_array ### declaring a array
### Read each line in the file with doesnt starts with '#' & keep it in array
grep -vE '^(\s*$|#)' < "$text_file" | while read -r -a cmd_array
do
"${cmd_array[#]}"
done
I'm not clear about the output/logging comment. If you need the output appended to a file, in addition to stdout/console), consider using the 'tee' (probably 'tee -a')
I tested with the input file inputfile
echo a
Function_1 '125' '' ''
# skip me
Function_1 '123' '' ''
echo b
and wrote this script:
declare -a cmd_array ### declaring a array
while read -r -a cmd_array
do
echo "${cmd_array[#]}"
"${cmd_array[#]}"
echo
done < <(grep -vE '^(\s*$|#)' inputfile)
For showing output in log and console, see https://unix.stackexchange.com/a/145654/57293
As #GordonDavisson suggested in a comment, you get a simular result with
source inputfile
ignoring comments and empty lines, and calling functions, so I am not sure why you would want an array. This command can be included in your master script, you do not need to modify the inputfile.
Another advantage of sourcing the input is the handling of multi-line input and # in strings:
Function_1 '123' 'this is the second parameter, the third will be on the next line' \
'third parameter for the Function_1 call'
echo "This echo continues
on the next line."
echo "Don't delete # comments in a string"
Function_1 '124' 'Parameter with #, interesting!' ''

Append text on a file in on bash script

I'm using cat to append some results in a file but the file its empty after the execution
start="$(date +'%s%3N')"
sleep 1
echo $par
end="$(date +'%s%3N')"
duration=$(($end-$start))
cat "$par $duration" >> result.dat
echo "$par $duration" >> result.dat
You use cat which will echo the content of the file with the name formed by "$par $duration". This will most likely not exist, so that you end up appending nothing to result.dat.

BASH SELECT CASE using list from a file as variables

name01=$(echo "Data 01")
name02=$(echo "Data 02")
echo "Please select data : "
PS3="Answer : "
optionname=(
"$name01"
"$name02"
"$name99")
select opt1 in "${optionname[#]}"
do
case $opt1 in
$name01) echo "$name01" ; break ;;
$name02) echo "$name02" ; break ;;
$name99) echo "Please enter the data : " ; read "name99" ; break ;;
*) echo invalid option;;
esac
done
This is part of my current script, and only have 12 data for now, but the amount and name of the data will change over time, so I need the data/variable (name01, name02, name03, ...) imported from a list from a separate text file. Let say the file look like this inside :
aa bb
aaaa ccc
ab cdd
Need advice,
Thanks in advance
If you just want to validate user input against a list of options in a file, then you could simply use grep:
Given a list of options in options.txt.
banana
apple
pear
And a script (option.bash):
#!/bin/bash
read -p 'Please enter your favourite fruit: ' fruit_input
if grep -q -o -x -- "$fruit_input" options.txt; then
echo "Your favourite fruit is: $fruit_input"
else
echo "The only fruits you're allowed to choose are:"
cat options.txt
fi
You can use grep to validate that the user entered an allowed option:
./option.bash
Please enter your favourite fruit: apple
Your favourite fruit is: apple
./option.bash
Please enter your favourite fruit: cheese
The only fruits you're allowed to choose are:
banana
apple
pear
Here is the update for my script, list is on /tmp/name_list
touch /tmp/number_list
touch /tmp/number_name_list
amount=$(cat /tmp/name_list | wc -l)
a=0
while [[ $a -lt $amount ]]; do
let a=$a+1
echo $a >> /tmp/number_list
name=$(sed -n "${a}p" /tmp/name_list)
echo "$a $name">> /tmp/number_name_list
done
cat /tmp/number_name_list
read -p "Please enter the number or enter new name : " input
if
grep -q -o -x -- "$input" /tmp/number_list
then
folder=$(sed -n "${input}p" /tmp/name_list)
echo "its $folder"
mkdir /tmp/"$folder"
else
echo "its $input"
mkdir /tmp/"$input"
fi
Thank you to #Robert Seaman for reminding me to use if then else instead of case

BASH: append loop output to an email

I want the output of this script to be a body of the email message but I don't want to redirect it to a file first and then to an email, basically no external login/output files - all action should be done within the script itself - is it possible to do it?
Example:
#!/bin/bash
email() {
echo "Results:"
}
for i in $(ls -1 test); do
if [ -f "test/$i" ]; then
echo "'$i' it's a file."
else
echo "'$i' it's a directory."
fi
done
email | mail -s "Test" an#example.com
Output:
$ ./tmp.sh
'd1' it's a directory.
'f1' it's a file.
It's easy:
#!/bin/bash
email() {
echo "Results:"
cat
}
for i in $(ls -1 test); do
if [ -f "test/$i" ]; then
echo "'$i' it's a file."
else
echo "'$i' it's a directory."
fi
done |email | mail -s "Test" an#example.com
You need the output of your test as input of email function, note that cat is just letting it pass through.

multiple sed operations creating empty file

When as part of shell script only one line is operating on a file using sed command the redirected file contains the updated data, as below
cat ${PROP_PATH}/${PROP_FILE} | sed "s!${ISTR_KEY}=.*!${ISTR_KEY}=${SIM_ISTR_KEY_VAL}!" > ${UPDATEDPROPS_DIR}/${PROP_FILE}
whereas when it is executed as part of a shell script, where after this another sed command updates the same file as in the below script at the end what i get is an empty file, why ? ..... ideas please.
(check 'switchAll2Sim()' function below)
#!/bin/ksh
#
SIM_ICR_KEY_VAL="http://www.example.com/sim/http/icr"
SIM_ISTR_KEY_VAL="http://www.example.com/sim/http/istr"
SIM_GT_KEY_VAL="http://www.example.com/sim/http/gtr"
#
ICR_KEY="interface.url.icr"
ISTR_KEY="interface.url.istr"
GT_KEY="interface.ws.url.gt"
## Property Files
PROP_PATH=""
PROP_FILE="properties"
##
DATE=`date +%m%d%Y`
DATETIME=`date +%m%d%Y-%T`
BCKUP_DIR=_bckup
UPDATEDPROPS_DIR=_updatedprops
# ----------------------------------
pause(){
echo "Press [Enter] key to continue..."
read fackEnterKey
}
permissions(){
chmod 777 ${UPDATEDPROPS_DIR}
}
backup(){
if [ ! -d "${BCKUP_DIR}" ]; then
mkdir ${BCKUP_DIR}
fi
if [ ! -d "${UPDATEDPROPS_DIR}" ]; then
mkdir ${UPDATEDPROPS_DIR}
fi
permissions
## keep backup of properties
cp ${PROP_PATH}/${PROP_FILE} ${BCKUP_DIR}/${PROP_FILE}_${DATETIME}
echo "Backup of property files completed at: " ${DATETIME}
}
#-------------------------------------------------------------
# switch all properties to SIM
#-------------------------------------------------------------
switchAll2Sim(){
backup
#
# update files
cat ${PROP_PATH}/${PROP_FILE} | sed "s!${ISTR_KEY}=.*!${ISTR_KEY}=${SIM_ISTR_KEY_VAL}!" > ${UPDATEDPROPS_DIR}/${PROP_FILE}
cat ${UPDATEDPROPS_DIR}/${PROP_FILE} | sed "s!${ICR_KEY}=.*!${ICR_KEY}=${SIM_ICR_KEY_VAL}!" > ${UPDATEDPROPS_DIR}/${PROP_FILE}
cat ${UPDATEDPROPS_DIR}/${PROP_FILE} | sed "s!${GT_KEY}=.*!${GT_KEY}=${SIM_GT_KEY_VAL}!" > ${UPDATEDPROPS_DIR}/${PROP_FILE}
echo "Switch all to SIM completed at: " ${DATETIME}
pause
}
# switch all properties to real
#-------------------------------------------------------------
switchAll2Real(){
pause
}
#-------------------------------------------------------------
dispCurrentStats(){
echo "Displaying current properties..."
echo "*********************************"
echo " File: " ${PROP_PATH}/${PROP_FILE}
grep ${ICR_KEY} ${PROP_PATH}/${PROP_FILE}
grep ${ISTR_KEY} ${PROP_PATH}/${PROP_FILE}
grep ${GT_KEY} ${PROP_PATH}/${PROP_FILE}
#
echo "*********************************"
pause
}
show_menus() {
clear
echo "~~~~~~~~~~~~~~~~~~~~~"
echo " M E N U"
echo "~~~~~~~~~~~~~~~~~~~~~"
echo "1. Display current properties"
echo "2. Switch all to real"
echo "3. Switch all to simulator"
echo "4. Exit"
}
# read input from the keyboard and take a action
read_options(){
read option
case $option in
1) dispCurrentStats ;;
2) switchAll2Real ;;
3) switchAll2Sim ;;
4) exit 0;;
*) echo "Please insert options 1 ~ 4";;
esac
}
# -----------------------------------
# Main - infinite loop
# ------------------------------------
while true
do
show_menus
read_options
done
Thanks, using '-i, says [sed: illegal option -- i]
Then you have to work with tmp files.
cp foo foo.tmp
sed "s/x/y/" foo.tmp > foo
/bin/rm foo.tmp
OR
sed "s/x/y/" foo > foo.tmp
/bin/mv -f foo.tmp foo
is probably more efficient.
I hope this helps.
Your problem is that cat is reading from the same file that sed is writing to.
cat foo | sed "s/x/y/" > foo
Will not work because cat and sed run at the same time, not one after the other.
To fix this try the -i option to sed.
sed -i "s/x/y/" foo

Resources