Checking if a file is empty in unix - shell

I'm trying to do something like
for i in {1..999}
do
#some commands here
if [ ! -s text${i}.txt ]
then
break
fi
done
But the file text${i} is not empty and this loop keeps exiting after going through it once but it should keep going and when I do
for i in {1..999}
do
#some commands here
if [ -s text${i}.txt ]
then
break
fi
done
The program just runs forever.

-s is for testing whether or not a file is empty, not -f. See here for some documentation.

Related

Bash script not recognizing file

I am attempting to write a bash script. In a test, I wrote a script to check for the existence of test.txt. However, no matter how many times I try to change the formatting, the code still does not recognize the file.
while [ "$INPUT" != "quit" ]; do
read INPUT
COMMANDFILE=test.txt
if [ -f $COMMANDFILE ]; then
echo "Found file!"
fi
done
I am 100% positive text.txt exists and is in the same folder as my script.
in this case I would add some debug lines to my script to make sure my thinking is correct. For instance:
while [ "$INPUT" != "quit" ]; do
read INPUT
COMMANDFILE=test.txt
echo "debug: now I'm in $( pwd ) directory. dir listing:"
ls -la
if [ -f $COMMANDFILE ]; then
echo "Found file!"
fi
done
also, please note that linux filenames are case sensitive (meaning you can have test.txt and TeSt.txt in the same directory). So, for instance if you have the file named TEST.TXT, [ -f test.txt ] will evaluate to false (unless test.txt exists as well)

Make script that reads argument from command line

I am running quantum chemical calculations by providing the command molcas -f file.input. I now have need for putting the molcas -f into a script that also tails the last 100 lines of the generated file.log, for me to quickly confirm that everything finished the way it's supposed to. So I want to run the script run.sh:
#!/bin/bash
molcas -f [here read the file.input from command line]
tail -100 [here read the file.log]
The question is how I can make the script read the argument I give, and then find on its own the output file (which has the same filename, but with a different extension).
Follow-up
Say I have a bunch of numbered files file-1, file-2, ..., file-n. I would save time if I instead of running
./run.sh file-1.input file-1.log
I run
./run.sh n n
or
./run.sh n.input n.log
assuming that the actual filename and placement of the number n is given in the script. Can that be done?
With this code:
#!/bin/bash
molcas -f "$1"
tail -100 "$2"
You will need to execute the script run.sh as follows:
./run.sh file.input file.log
to be hornest I have/had no clue over molcas, so I jumed to this side to get basic understandings.
The syntax shoould look like this ...
#!/bin/bash
# waiting for input
read -p "Enter a filename (sample.txt): " FILE
# checking for existing file
if [ -e "$FILE" ]; then
read -p "Enter a command for moculas: " CMD
else
echo "Sorry, \"${FILE}\" was not found. Exit prgramm."
exit 1
fi
# I am not sure how this command works.
# maybe you have to edit this line by your self.
molcas $FILE -f "$CMD"
# checking for programm-errors
ERRNO=$?
if [ "$ERRNO" != "" ] && [ "$ERRNO" -gt 0 ]; then
echo "Molcas returned an error. Number: ${ERRNO}"
exit 1
fi
# cuts off the fileending (For example: sample.txt gets sample)
FILENAME="${FILE%.*}"
# checking other files
ERRFILE="${FILENAME}.err"
tail -n 100 $ERRFILE
LOGFILE="${FILENAME}.log"
tail -n 100 $LOGFILE
exit 0
I would have posted more, but its not clear what to do with this data.
Hope this helps a bit.

Check for existance of directory always fails in Bash Script

I have a problem that has been bugging me for a few hours now. I have created a parameter --file-dir using getopt, which assigns a directory for the program to use. Following the parameter, the user has the choice to choose whatever directory they please. To keep the program stable, I check to see whether that directory even exists. The following code is what I have currently and it always returns "Directory does not exist. Terminating." even when I search for my /home directory.
-a|--file-dir) FILE_DIR=$2 ;
if [ ! -d "$FILE_DIR" ]; then
echo "Directory does not exist. Terminating." ;
exit 1;
else
echo "Directory exists." ;
fi ;
shift;;
Any input is much appreciated. The getopt's work fine with echo tests and such but fail when checking for directories.
It would be a good idea to check if you're really having the right argument for it:
-a|--file-dir) FILE_DIR=$2 ;
if [ ! -d "$FILE_DIR" ]; then
echo "Directory \"$FILE_DIR\" does not exist. Terminating." ;
exit 1;
else
echo "Directory exists." ;
fi ;
shift;;
If not certainly the problem is not in the checker but somewhere in your argument-parsing loop.
I had an issue with the same behavior: checking for a directory in the command line worked as expected, but always failed when done in a script.
I was running this script under git bash for Windows:
while read -r i; do
[ ! -d "$i" ] && echo "No $i"
done < "$1"
Windows' line endings (\r\n) can cause issues when splitting lines. Each test actually checks for directory\r instead of directory. Therefore, I needed to run the read command with the correct delimiter:
while IFS=$'\r\n' read -r i; do
It is possible that OP also had a similar issue, where non-printable characters got in the way.

how to check for file with wildcards existance in while loop in shell script

I'm writing a bash shell script where I want to implement a sleep sequence as long as a file exists. Now, in the simplest case this is something like:
while [ -f fileName ]
do
echo "waiting"
sleep 1
done
Now, in my situation the first issue is the following: I want to use wildcards in the fileName. This can be resolved by something like:
fileName="$path/$prefix*$suffix"
while [ -f $fileName ]
do
echo "waiting"
sleep 1
done
However, this fails if more than one file matching the fileName
./testWait.sh: line 11: [: /home/nrc11/egsnrc/BEAM_TB_jaws/130318110457_s.lock: binary operator expected
how do I resolve this?
Here is the (semi) specific example:
#!/bin/bash -u
timeStamp="130318110457"
echo "prefix of files: $timeStamp"
beamDir=$(awk '{ print $0 }' $timeStamp/$timeStamp.beamDir)
file="$EGS_HOME$beamDir/$timeStamp*.lock"
echo $file
while [ -f $file ]
do
echo "waiting"
sleep 1
done
You can use grep on the expanded wildcard to verify that it returns something else than an asterisk after the time stamp:
while echo $file | grep "^$EGS_HOME$beamDir/$timeStamp"'[^*]' ; do
echo "Waiting..."
sleep 1
done
I am very user about this, I trying doing this long back, I used some thing called inotify, a package in linux, try it out, it actually makes your life more easier.

Bash: Only allow Pipe (|) or Redirect(<) to pass data, and show usage otherwise

I have a script which takes in several arguments.
Now, I have modified the script to except multiple file names and operate on them.
I also want this script to execute when I am receiving input via a pipe (|) or a redirected input (<).
But, I do not want the script to wait for input on terminal when none of the above three inputs are provided, and rather show usage instructions.
I am using the following function:
# PIPED CONTENT
if [ "$#" == "0" ]; then
READINPUT="1"
if [ "x$TEXTINPUT" == x"" ]; then
READINPUT=1
TMPFL=`tempfile -m 777`
while read data; do
echo "${data}" >> $TMPFL
done
TEXTINPUT="`cat $TMPFL`"
rm $TMPFL
fi
# if [ "x$TEXTINPUT" == x"" ]; then
# if [ "$#" == "0" ]; then usage; fi
# fi
fi
Any help is appreciated.
Regards
Nikhil Gupta
if test -t 0; then
echo Ignoring terminal input.
else
process -
fi
The -t test takes a file descriptor as parameter (0 is stdin) and returns true if it is a terminal.
Please be aware that there are two different "test" commands: the built in bash command, and the "test" program which is often installed as /usr/bin/test, part of the coreutils package. The two provide the same functions.
[[ -t 0 ]]
is equivalent to
/usr/bin/test -t 0
You may run either of the above on a "bash" command line, with the same results.

Resources