gomibako
gomibako

Reputation: 83

How to use printf with conditional arguments

I'm trying to print file if $files is 0 or 1 and files if greater than 1. What is the concise way to do this in bash?

I tried using 'printf' as follows,

files=13;
printf 'There are %s file%s' $files $(($files > 1 ? 's' : ''))

and as expected this doesn't work out.

Could someone tell me how to achieve this?

Upvotes: 3

Views: 3732

Answers (4)

gomibako
gomibako

Reputation: 83

Because %b format specifiers interpret backslash escapes you can still use ? operator to substitute a single character.

$ files=1
$ printf 'Removed %s file%b\n' $files \\$(($files > 1 ? 163 : 0))
Removed 1 file

$ files=15
$ printf 'Removed %s file%b\n' $files \\$(($files > 1 ? 163 : 0))
Removed 15 files

Upvotes: 0

rici
rici

Reputation: 241881

If it were just selecting between file and files, you could do this, although it's not as concise as one might like:

printf "The search found %d file%.*s.\n" $files $((files != 1)) "s"

But in the statement in the OP, you would also need to change are to is to maintain verb/object agreement. In this case, it is almost certainly easier and more readable to use a conditional, but you could use an array:

formats=("is %d file" "are %d files")
printf "There ${formats[files!=1]}.\n" $files

Upvotes: 4

DevSolar
DevSolar

Reputation: 70353

Well, actually, if you want grammatically correct output ("are" vs. "is"), you can just as well write it out instead of trying to make do with a single line...

if [[ $files -eq 1 ]]
then
    echo "There is 1 file."
else
    echo "There are $files files."
fi

Better to read, less chance of getting it wrong, and probably faster as well as it does only one test, and does not start subshells.

Upvotes: 1

fedorqui
fedorqui

Reputation: 290135

Create a condition like this:

printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")

With $( [ $files -gt 1 ] && echo "s" || echo "") we are opening a shell in which the values are checked. In case a condition is matched, s is printed.

To also handle the is/are, you can add another condition:

printf 'There %s %s file%s\n' $( [ $files -eq 1 ] && echo "is" || echo "are" ) $files $( [ $files -gt 1 ] && echo "s")

Test

$ files=0
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 0 file
$ files=1
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 1 file
$ files=15
$ printf 'There are %s file%s\n' $files $( [ $files -gt 1 ] && echo "s")
There are 15 files

Upvotes: 1

Related Questions