0

The bash script snippet

folder="some folder's name"
a="$folder/"*".pdf"
if [ "$a" != "$folder"'/*.pdf' ]
then
    echo check
fi

never prints check.

I'd expect it to print check iff there is at least 1 file whose name ends in .pdf in folder $folder.

echo $a and echo "$folder"'/*.pdf' print exactly what I'd expect them to print: The former prints the matched paths iff there is at least 1 *.pdf file in the specified folder and otherwise prints what the latter prints. The latter always prints the name of the specified older concatenated with /*.pdf.

  1. Why does bash behave like that?
  2. How do I make it work?
UTF-8
  • 3,175
  • 5
  • 23
  • 50
  • 3
    The proper way to do it is described here: [Test if there are files matching a pattern in order to execute a script](https://unix.stackexchange.com/q/79301/22142) – don_crissti Oct 23 '17 at 19:20
  • With bash, that condition (`[ "$#" -gt 0 ]`) always passes. It think this is because bash just doesn't replace the asterisk if there is no match, so there always is at least 1 result. – UTF-8 Oct 23 '17 at 22:41
  • No. If you bother reading the answer there you'll see there's a `shopt -s nullglob` _before_ that condition. – don_crissti Oct 23 '17 at 22:43
  • Oh, you're right. I'm sorry. With that option set, it works. Thank you. – UTF-8 Oct 23 '17 at 22:53

2 Answers2

2

This expression "$folder/"*".pdf" will expand to all possible filenames that end with .pdf.
Why? The * sign retains its special meaning i.e. globbing.

While this string "$folder"'/*.pdf' is just a concatenation of 2 separate strings "$folder" and '/*.pdf'.
As * sign enclosed in single quotes - it loses its special meaning.


According to your main goal check if the current folder has at least one .pdf file and printing some "pdf file found!" phrase on success:

if [ ! -z `find foldername -type f -name "*.pdf" -print -quit` ]; then 
    echo "pdf file found!"
fi
RomanPerekhrest
  • 29,703
  • 3
  • 43
  • 67
1

Your if statement doesn't work, because $a enclosed in double quotes is just a string containing a * (compare echo "$a" with echo $a). If you remove the double quotes, your if statements fails as soon as there are more than one files matching.

don_crissti's link has good solutions.

sborsky
  • 1,018
  • 7
  • 12
  • We both agree that the right expression doesn't depend on the folder's contents, right? If there is no file in the folder, bash doesn't replace the wild card `*` in the variable assignment. So my plan is to check whether that replacement happened. – UTF-8 Oct 23 '17 at 20:06
  • Yes, Bash does not replace `*` when there is no match (corrected my answer). I still don't think you can handle the case of >1 matches (many pdf files in the folder) this way. If you are not enclosing `$a` in `"`, the `if` statement is going to fail with `too many arguments`. If you are enclosing `$a` in `"`, `*` is not going to be resolved/replaced by file names. Thus, I don't think `if` in combination with file name expansion is a good idea. I have been using `ls`' exit status before, but there other options. – sborsky Oct 23 '17 at 20:26