chmod command is not working in shell script - bash

I am writing a script that needs to create a file if an argument is passed to he script.
If no argument is passed then it will ask for fileName but it needs to have default permission as -rwx- --- - ---.
I am using this command chmod a=-rwx to remove all the default permissions and then i am using chmod u=+rwx to get the desired permission as stated but it is not working.
Can anyone help please?
#!bin\bash
if [ $#==0 ]; then
echo "Please enter a file name?"
read fileName
if [ -f $fileName ]; then
echo "File already exist! Opening for Editing"
sleep 3
nano $fileName
else
echo "File created with the name $fileName"
echo "Opening $fileName for editing "
sleep 3
echo "#!bin\bash" >$fileName
nano $fileName
fi
elif [ -f $1 ]; then
echo "File already exists with the name $1"
echo "Opening for editing"
sleep 3
nano $1
else
fileName="$1"
chmod a=-rwx $fileName
chmod u=+rwx $fileName
echo "File created with the name $filename"
echo "Opening $fileName for editing "
echo "#!bin\bash" >$fileName
sleep 3
nano $1
fi

Your chmod syntax is incorrect. The operation is either = to set the mode to a specific value, + to add modes, or - to remove modes; you can't combine them with =+ and =-.
You can perform multiple operations on a single file by separating them with ,.
So it should be:
chmod go-rwx,u+rwx "$fileName"
Another problem:
if [ $#==0 ]
should be
if [ $# -eq 0 ]
Use -eq for numeric comparisons, and spaces are needed around operators in shell conditions.
Third problem: You're doing the chmod before you create the file. Put it after
echo "#!/bin/bash" >"$fileName"
Fourth problem: #!bin\bash should be #!/bin/bash.
Finally, remember to quote your variables, in case they contain spaces.

Related

Handling files with spaces in a bash selection menu

I am trying to make this script handle file with spaces in them. it is supposed show and execute the content of files in a directory. when I select a file with a space in it, bash fails with bash: foo: no such file or directory, What am I missing to make this handle files correctly
# /etc/skel/.bashrc
#Interactive shell detection
if [[ $- != *i* ]] ; then
# Shell is non-interactive. Be done now!
return
fi
#kv-bash (easy) var database & setup of info
echo "type 'menu' for a bash menu"
#done####################
#to easily launch crouton enviroments
addentry() {
cd ~/.sslm
echo "Name your menu entry."
read entry
sleep 1s
if [ -e "$entry " ]
then
echo "Error, Menu entry already exists"
addentry
else
echo "what do you want the entry to do?"
read entryexec
echo "$entryexec && menu"> ~/.sslm/"$entry"
echo "done"
cd ~/
fi
sleep 1s
}
###################
delentry() {
cd ~/.sslm
ls -x
echo "what entry do you want to delete?"
read del
rm "$del"
echo "the work has been done, he is dead"
}
###################
menu() {
clear
cd ~/.sslm
echo "-- simple shell launcher menu v1.o --"
# set the prompt used by select, replacing "#?"
PS3="Use number to select a file or 'exit' to leave: "
# allow the user to choose a file
select filename in *
do
# leave the loop if the user says 'stop'
if [[ "$REPLY" == exit ]]; then
cd ~/
break
fi
# complain if no file was selected, and loop to ask again
if [[ "$filename" == "" ]]
then
echo "'$REPLY' is not a valid number"
sleep 1s
continue
fi
# now we can use the selected file, trying to get it to run the shell
script
. $filename
# it'll ask for another unless we leave the loop
break
done
}
menu
also, this is on a chromebook, so there is no apt.
At this part:
script
. $filename
I just needed to change to . "$filename"
thx #PesaThe

How to execute a file that is located in $PATH

I am trying to execute a hallo_word.sh that is stored at ~/bin from this script that is stored at my ~/Desktop. I have made both scripts executable. But all the time I get the problem message. Any ideas?
#!/bin/sh
clear
dir="$PATH"
read -p "which file you want to execute" fl
echo ""
for fl in $dir
do
if [ -x "$fl" ]
then
echo "executing=====>"
./$fl
else
echo "Problem"
fi
done
This line has two problems:
for fl in $dir
$PATH is colon separated, but for expects whitespace separated values. You can change that by setting the IFS variable. This changes the FIELD SEPARATOR used by tools like for and awk.
$fl contains the name of the file you want to execute, but you overwrite its value with the contents of $dir.
Fixed:
#!/bin/sh
clear
read -p "which file you want to execute" file
echo
IFS=:
for dir in $PATH ; do
if [ -x "$dir/$file" ]
then
echo "executing $dir/$file"
exec "$dir/$file"
fi
done
echo "Problem"
You could also be lazy and let a subshell handle it.
PATH=(whatever) bash command -v my_command
if [ $? -ne 0 ]; then
# Problem, could not be found.
else
# No problem
fi
There is no need to over-complicate things.
command(1) is a builtin command that allows you to check if a command exists.
The PATH value contains all the directories in which executable files can be run without explicit qualification. So you can just call the command directly.
#!/bin/sh
clear
# r for raw input, e to use readline, add a space for clarity
read -rep "Which file you want to execute? " fl || exit 1
echo ""
"$fl" || { echo "Problem" ; exit 1 ; }
I quote the name as it could have spaces.
To test if the command exists before execution use type -p
#!/bin/sh
clear
# r for raw input, e to use readline, add a space for clarity
read -rep "Which file you want to execute? " fl || exit 1
echo ""
type -p "$fq" >/dev/null || exit 1
"$fl" || { echo "Problem" ; exit 1 ; }

Shell script to check a log file and print the errors that are found in it

I am pretty new to shell scripting . I am trying to write a script to check for logfile for errors (error strings are hardcoded), and i have to print the lines containing the error . i am able to write the logic but need pointers to read a file from user input.
Appreciate the help thanks.
Logic:
Accept the logfile patch from user
Check if the logfile is present or not
If present search the file for lines containing the error string (eg. Error, ORA)
Print the lines containing error strings , also write the output to a logfile
Read the log file from user
Set error strings
search="ERROR"
set a path for output file
outfile="file1.txt"
Execution logic
find "$mydir" -type f -name "$filename" |while read file
do
RESULT=$(grep "$search" "$file")
if [[ ! -z $RESULT ]]
then
echo "Error(s) in $file: $RESULT" >> "$outfile"
fi
done
I'm not sure what you mean with "need pointers to read a file from user input". I assume "pointers" are script arguments.
You can use this script:
#!/bin/bash
expected=outfile
for f in $#
do
if [ "$expected" = outfile ]; then
OUTFILE=$1
expected=search
elif [ "$expected" = search ]; then
SEARCH=$2
expected=files
elif [[ -f $f ]]; then
RESULT=`grep "$SEARCH" $f`
if [ -n "$RESULT" ]; then
echo -e "\n"
echo "Error(s) in "$f":"
echo $RESULT
echo -e "\n" >> $OUTFILE
echo "Error(s) in "$f":" >> $OUTFILE
echo $RESULT >> $OUTFILE
fi
fi
done
Invoke with:
scriptname outfile search files
where:
scriptname: is the name of file containing the script.
outfile: the name of the output file
search: the text to be searched
files: one or many file name or file patterns.
Examples (I assume the name of the script is searcherror and it is in the system path):
searcherror errorsfound.txt primary /var/log/*.log
searcherror moreerrors.txt "ORA-06502" file1.log /var/log/*.log ./mylogs/*

bash copy file to new desintation if it doesnt exists make a new directory

Hello i am currently optimizing some code i have and am now wondering why this snippet of code does not work.
what is supposed to happen is when i copy the file i have to type in a destination for the copy if i type a destination that doesn't exist then the script will create a directory and copy that file to it.
this is what i have and i am wondering why it is not working
echo "Current Directory "
ls -a;
echo -n "Please Enter file name to Copy: "
read fileToCopy
echo -n "Enter Destination for Copy: ~/ "
read location
if [ -d $location ]
then
cp $fileToCopy $location
echo "File Successfully Copied to ~/ $location "
elif [ !-d $location ]
then
mkdir $location
cp $fileToCopy $location
echo "$location was created and the File was Copied to It! "
echo -n "Press Enter to Continue: "
else
echo "That file Does Not Exist! "
fi
Two issues:
One:
elif [ !-d $location ]
You need a space between ! and -d.
Two:
Quote your variables.
It's always good to error check. What if the user didn't enter a directory name or a file to copy?
In shell, a null variable will cause an error in a statement like this:
if [ $dir -eq foo ]
then
…
fi
That's because the shell will directly substitute the value and then interpret the line. If $dir is null, the statement will be:
if [ -eq foo ]
then
…
fi
This isn't valid. If you had quotes around $dir:
if [ "$dir" -eq foo ]
then
…
fi
You'd get this:
if [ "" -eq foo ]
then
…
fi
Which is valid.
If you're using bash it's preferable to use the double square brackets:
if [[ $dir -eq foo ]]
then
…
fi
This is a special improved syntactic test that will handle null variables and variables with spaces without having to use quotes.
The ! is a special shell operator that negates the return value of a command/statement. For the shell to understand the operator, you must make sure there is white space on either side of it. Also test the output of your mkdir statement to make sure it worked. And use the -p parameter. This will create parent directories.
if [[ ! -d "$dir" ]]
then
if ! mkdir -p "$dir"
then
echo "Could not create dir '$dir'" 1>&2
exit 2
fi
fi
Note that I always put quotes around my variable and I use the if statement to test to see if my command succeeded or not. After all, the user might have tried to create a directory where I don't have write permission.
One more secret trick. You can use set -xv to turn on shell script debugging. This will print out each statement as written and then as the shell interprets it. To turn it off use set +xv.

performing multiple backups at the same time with a bash script

Create a script to backup a file or directory tree by making a zip of the file(s) and copying it $HOME/Backups. The zipfile name should include what it is backing up, and the date the file was created. The script should take a random number of arguments specifying what to backup. If it is not given at least one item to include in the backup, it should complain. Ive got most of it to work but im having issues with multiple files ie file1 file2 to backup at the same time
#!/bin/bash
clear
echo
echo "Use this script to backup files to your home/backups directory"
echo
ls -la
echo
echo "================================================================"
echo
echo -n "Input file(s)/dir to backup: " ; read filez
while [ "$filez" == "" ] ; do
echo -n "You didnt input a filename, try again: " ; read filez
done
while [ ! -e "$filez" ] ; do
echo -n "No such file/dir, try again: " ; read filez
while [ "$filez" == "" ] ; do
echo -n "You didnt input a filename, try again: " ; read filez
done
done
echo
echo "================================================================"
echo
echo -n "Input name of backup file you wish to create(date automatically included): " ; read filezname
while [ "$filezname" == "" ] ; do
echo -n "You didnt input a filename, try again: " ; read filezname
done
zip -r $HOME/backups/$filezname"_$(date +%F)" $filez
Personally, I'm a fan of bash scripts taking arguments right from the command line:
script arg1 arg2 arg3 ...
Bash takes arguments using the special array $#, and you can do arguments processing with shift. Something like this:
#!/bin/bash
filezname=$1
shift
filez=""
for file in "$#"
do
filez="$filez $file"
done
if [[ $filez == "" ]]
then
echo "Give me argz! Nom nom nom!"
exit 0
fi
# Do stuff
What this does is it takes the first argument, takes it as the name of the zip file, and then slurps the rest of the filenames you want to zip up into a big long space-separated string that you can play with.

Resources