The problem:

I want to be able to run a program within a bash loop over each .fna file in a directory, but I also want the name of the output file to have the same file name (without the extension), the problem is that the program uses the single quotes to specify its output file. So when I run my script, it just prints a file called:


The code:

 for fna in $(find . -name "*.fna")
    outputname = ${fna%.fna}
    outputfile = $outputname.rrna
    barrnap $fna --outseq 'outputfile'

Example input

A file named:


With an example of the contents:

>NZ_GG666849.1 Bifidobacterium longum subsp. longum ATCC 55813 SCAFFOLD1, whole genome shotgun 

Desired output:

An output file from the program named:


I apologise for the messiness of this, I'm having trouble thinking of the best way of explaining the problem, if anyone can suggest to me an improvement to the title I will instantly change it.


The program does not use single quotes. The single quotes are used to prevent the shell from performing variable expansions on the quoted string. The quotes will be removed by the shell before calling the program.

In this case, the single quotes do nothing as the string that they quote is just a plain string with no expansions for the shell to perform (this is an error in your code, you probably wanted $outputfile with double quotes).

If your files are in the current directory (and only there), you could do

for fasta in ./*.fna; do
    barrnap --outseq "${fasta%.fna}.rrna" "$fasta"

or, with an intermediate variable,

for fasta in ./*.fna; do
    barrnap --outseq "$outfile" "$fasta"

Here we use double quotes instead of single quotes because we want the shell to perform the expansion within them. I have also moved the input filename to the end of the command line in the invocation of barrnap in accordance with the manual.

If your files are located in any number of subdirectories in the current directory, and you need to use find, then don't loop over the output of find but let find call your program:

find . -type f -name '*.fna' -exec sh -c '
    for fasta do
        barrnap --outseq "${fasta%.fna}.rrna" "$fasta"
    done' sh {} +

Here, find acts like a generator of pathnames for the shell loop.


Your code also have a couple of syntax errors in that assignments should be done without spaces around =. Variable expansions should furthermore be double quoted.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.