Is there an efficient way to check an input BAM in R? I'm writing a function in R for an R package which takes as input a BAM. 

my_func = function(my_bam){
    if (!file.exists(my_bam)){
        stop("Input a valid BAM file.")
    }

    ## do awesome stuff with BAM

}


Trying to write robust software, I would like to do more of a check whether this BAM is actually a BAM. Above, I'm just using file.exists(). 

I could also do something simple like "check whether the file has the extension *.bam" with 

grepl('*.bam', my_bam)  ## TRUE for file.bam, FALSE for file.txt


However, is there a quick way to check that the input is actually a BAM? I would prefer to throw an error here, if the user inputs a *txt or *bedpe. 

I don't think it's necessary to validate the BAM per se, whereby I believe most users rely upon Picard:

https://broadinstitute.github.io/picard/command-line-overview.html#ValidateSamFile

My first thought was Rsamtools for this operation:

https://bioconductor.org/packages/release/bioc/html/Rsamtools.html

However, it doesn't appear that there is a function here which checks the user inputs a BAM, e.g. BamFile() doesn't appear to throw an error

&gt; library(Rsamtools)
&gt; fake_bam = 'nonsense_string.bam'   ## a string I made up, not a real BAM
&gt; BamFile(fake_bam)
class: BamFile 
path: nonsense_string.bam
index: NA
isOpen: FALSE 
yieldSize: NA 
obeyQname: FALSE 
asMates: FALSE 
qnamePrefixEnd: NA 
qnameSuffixStart: NA 


How could I "check" that the user is inputting a BAM file? Perhaps pipe to samtools (which doesn't feel very stable in terms of software)?
You won’t know whether it’s a valid BAM file until you attempt reading it in full; even Devon’s method (which I recommend) only does a superficial check — i.e. it checks whether (parts of) the BAM header can be read correctly. However, this doesn’t guarantee that the file isn’t truncated or contains invalid data.

This is of course a more general problem, but it’s perhaps a bit stranger for BAMs (and other biological formats), as it’s relatively frequent to end up with technically invalid files that were produced by existing software. The only recourse is actually trying to use the file, and to handle errors appropriately.

For a very quick check™ you could also pass the file through gunzip and test whether the “magic bytes” at the beginning of the file equal 'BAM\1':

bgzf_stream = gzfile(filename, 'r')
magic = readChar(bgzf_stream, 4)
stopifnot(identical(magic, 'BAM\1'))