I'm not specifying my If Statement in bash correctly, but I'm not sure what exactly I'm doing wrong.
I have hundreds of participants who completed differing numbers of study procedures so they have a different number of available files. I added an if statement to specify how many files we should expect to find for each participant after a processing procedure. It should iterate through each participant, assign a value between 3 and 5 to a variable based on the ID, then use the value of that variable to look for a certain number of files.
# SUBJECTS is a concatenated list of IDs
for i in ${SUBJECTS}; do
# Different subjects have a different number of files.
# I want to specify how many files bash should look for based on ID.
# This first if statement should identify whether the current iteration of i matches any of the identified IDs.
# If so, it should specify that bash should be looking for 4 files.
if [[ ${i} -eq "XX001" ||\
${i} -eq "XX002" ||\
${i} -eq "XX003" ]];
then
NFILES=4
# ... and if any iterations of i match these IDs, bash should look for 3 files
elif [[ ${i} -eq "XX004" ||\
${i} -eq "XX005" ]];
then
NFILES=3
# ... and for everyone else, bash should look for 5 files.
else
NFILES=5
fi
# Now, for each participant, iterate through the number of files we expect they should have
for j in `seq -w 1 ${NFILES}` ; do
# ... and check whether a file of this name exists in this location
if [ ! -f "${FILEPATH}/FILENAME_${i}_${j}.nii.gz" ]; then
# If it does not, note which ID and File is missing at the end of this document
echo "${i}; FILE ${j}" >> ${FILEPATH}/MissingFiles.txt
fi
done
done
If I run this script without the first If Statement, it correctly identifies that files exist for participants, but it just also gives a lot of false negatives too (e.g., if a participant only has three files, the output will suggest files 4 and 5 are missing, even though it's what is expected). When I add the If Statement, the computer seems to assume all participants meet the first condition for some reason, so it thinks all participants have 4 files.
I'd been using a lot of other threads like this one and this one to find solutions, but without much luck. Any help is greatly appreciated!
CodePudding user response:
In a [[ ]]
conditional expression, the -eq
operator does numeric comparisons, not string comparisons; you want the =
operator (or equivalently ==
).
Note: the syntax and operator semantics are confusingly different between [[ ]]
, [ ]
, and (( ))
expressions. See this Unix&Linux answer and BashFAQ #31. If you're writing for bash (i.e. your script doesn't need to be able to run under dash, or some other shell that doesn't have [[ ]]
), I recommend avoiding [ ]
entirely and using [[ ]]
for most tests, but (( ))
is ok for strictly arithmetic things.
In this case, though, since you're comparing a variable against a bunch of possible values, I'd recommend a case
statement. That's what they're for.
case "$i" in
XX001 | XX002 | XX003 )
NFILES=4 ;;
XX004 | XX005 )
NFILES=3 ;;
...
* )
NFILES=5 ;;
esac
You can also use glob patterns here, so XX00[123] )
would match "XX001", "XX002", or "XX003".
I'd also recommend switching to lower- or mixed-case variable names, to avoid conflicts with the many all-caps names that have special meanings.