Bash- How to check if file is empty in a loop - bash

I need to check in Bash file is empty,
if it's empty keep tracking him until something is written to it.
In case something was written to it echo it to the screen and stop checking the file content.
for [ -s diff.txt ]; do
echo "file is empty - keep checking it "
done
echo "file is not empty "
cat diff.txt

Why not just use a while?
while ! [ -s diff.txt ]; do
echo "file is empty - keep checking it "
sleep 1 # throttle the check
done
echo "file is not empty "
cat diff.txt
The loop will run as long as ! [ -s diff.txt ] is true. If you prefer, you can use until instead of while and remove the negation (!).

Related

chmod command is not working in shell script

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.

bash - Comparing variables

I am trying to do the following in bash:
get my external IP
read first line of a file
compare both values
if it is not the same, delete the file and recreate it with the current address
I really don't know why this fails, all my script does is to output my current address and the first line of the file (which by the way is simply "asd" for testing)
#!/bin/bash
IP= curl http://ipecho.net/plain
OLD= head -n 1 /Users/emse/Downloads/IP/IP.txt
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
$IP> /Users/emse/Downloads/IP/IP.txt
exit
fi
Some obvious problems in your script:
Don't put spaces on either side of equal sign if you want to do assignment
You want the output of curl, head so wrap them in backticks (`)
You want to write $IP into the file, not to execute the content of it as a command, so echo it
The script becomes:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" = "$OLD" ]; then
exit
else
rm /Users/emse/Downloads/IP/IP.txt
echo $IP > /Users/emse/Downloads/IP/IP.txt
exit
fi
Excellent answer qingbo, just a tad bit of refinement:
#!/bin/bash
IP=`curl http://ipecho.net/plain`
OLD=`head -n 1 /Users/emse/Downloads/IP/IP.txt`
if [ "$IP" != "$OLD" ]; then
echo $IP > /Users/emse/Downloads/IP/IP.txt # > creates/truncates/replaces IP.txt
fi

trying to test zero length output from command in shell script

I'm sort of a newbie when it comes to shell scripting. What am I doing wrong?
I'm trying to grep a running log file and take action if the grep returns data.
# grep for "success" in the log which will tell us if we were successful
tail -f file.log | grep success > named_pipe &
# send signal to my server to do something
/bin/kill -10 $PID
timeout=0;
while : ; do
OUTPUT=$(cat < named_pipe)
if test [-n] $OUTPUT
then
echo "output is '" $OUTPUT "'"
echo_success
break;
else
timeout=$((timeout+1))
sleep 1
if [ $timeout -ge $SHUTDOWN_TIMEOUT ]; then
echo_failure
break
fi
fi
done
I'm finding that even when "success" is not in the log, test [-n] $OUTPUT returns true. This is because apparently OUTPUT is equal to " ". Why is OUTPUT a single space rather than empty?
How can I fix this?
Here's a smaller test case for your problem:
output=""
if test [-n] $output
then
echo "Why does this happen?"
fi
This happens because when $output is empty or whitespace, it expands to nothing, and you just run test [-n].
test foo is true when foo is non-empty. It doesn't matter that your foo is a flag wrapped in square brackets.
The correct way to do this is without the brackets, and with quotes:
if test -n "$output"
then
...
fi
As for why $OUTPUT is a single space, that's simple: it isn't. echo just writes out its arguments separated as spaces, and you specified multiple arguments. The correct code is echo "output is '$OUTPUT'"

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.

Checking whether file exists

I'm in the final stages of a project and need to create a script that will run an executable a given number of times with varying input. One of the inputs is a file kept in a separate folder from the executable.
Before doing anything, I want to check whether the file exists. There are two possible file inputs that can be given, so I need to compare them. The possible inputs are
execute cancer 9
execute promoter 9
where cancer and promoters are the datasets to be used in the program and 9 is the number of times the script loop has to execute.
Here's what I've come up with:
#!/bin/bash
#Shell script to execute Proj 4 requirements while leaving the folder
#structure alone separated.
file1= "Data/BC/bc80-train-1"
file2= "Data/Promoters/p80-train-1"
if [ "$1" == "cancer" ] then #execute command on the cancer dataset
echo "Executing on the cancer dataset"
if [ -f "$file1" ] then
echo "$file1 file exists..."
else
echo "$file1 file Missing, cancelling execution"
echo "Dataset must be in ../Data/BC/ and file must be bc80-train-1"
fi
elif [ "$1" == "promoter" ] then #execute on the promoter dataset
echo "Executing on the promoter dataset"
if [ -f "$file2"] then
echo "$file2 file exists..."
else
echo "$file2 file missing, cancelling execution"
echo "Dataset must be in ~/Data/Promoters/ and file must be p80-train-1"
fi
fi
The problem with this is it opens the files and outputs them to terminal, where each line ends in : command not found
I thought the -f and -e flags were used to check whether a file exists. So why is the file content being output to the terminal?
Drop the space to the right of = in:
file1= "Data/BC/bc80-train-1"
file2= "Data/Promoters/p80-train-1"
Also the keyword then should be on a line by itself or if on the same line as if should have a ; before it:
if [ condition ] ; then
...
fi
OR
if [ condition ]
then
...
fi
Your error messages mix ../Data/ and ~/Data/, but your file1 and file2 don't have either .. or ~ in their definitions:
file1= "Data/BC/bc80-train-1"
file2= "Data/Promoters/p80-train-1"
Remove the space after the = in file1= and file2=
Don't repeat yourself, use a function:
#!/bin/bash
checkfile() {
echo "Executing on the $1 dataset"
file="$2/$3"
if [ -f "$file" ] then
echo "$file file exists..."
else
echo "$file file Missing, cancelling execution"
echo "Dataset must be in $2 and file must be $3"
fi
}
case $1 in
cancer)
checkfile $1 Data/BC bc80-train-1
;;
promoter)
checkfile $1 Data/Promoters p80-train-1
;;
*)
echo "Error: unknown dataset. Use 'cancer' or 'promoter'"
;;
esac

Resources