In the directory I am working on I have two files with the extension .sam:


For each of these two files, I need to apply a command that looks like the following:

samtools view -Sb pattern.sam > pattern.bam

I am trying to use xargs for that. What I am trying to do is to capture the prefix before _aligned_minimap and use that to save to my output. What I tried is the following:

ls *.sam | cut -d "_" -f 1 | xargs -i samtools view -Sb {}_aligned_minimap.sam > {}_aligned_minimap.bam

I would be expecting to have to files generated i.e. PD180425_aligned_minimap.bam and PD180793_aligned_minimap.bam. Although my command is running, I see on the directory I am working on that the file {}_aligned_minimap.bam was generated, which indicates that the input I am trying to capture with xargs (PD180425 and PD180793) is not working.

How can I go about doing this?


2 Answers 2


My preferred approach for this would be something like this:

for SAM_FILE in *.sam; do
    samtools view -Sb "$SAM_FILE" > "${SAM_FILE/sam/bam}"

Which can be made into a one liner like

for SAM_FILE in *.sam; do samtools view -Sb "$SAM_FILE" > "${SAM_FILE/sam/bam}"; done

This uses parameter expansion to change the output file extension: https://wiki.bash-hackers.org/syntax/pe

In my opinion this style makes it clear what you are trying to do if you or others stumble upon your scripts at a later time.

  • 4
    You can also use "${SAM_FILE%.sam}.bam" to change the extension. It has two advantages over ${//}: 1) it's a standard feature, unlike ${//}, so works in any sh-like shell, and 2) it makes the replacement only at the end of the string, so it doesn't matter if the middle of the filename contains sam.
    – ilkkachu
    Commented Jul 26, 2019 at 9:11

My command worked with slight modifications and I reckon it is simpler and less verbose than a for loop:

ls *.sam | cut -d "_" -f 1 | xargs -I {} bash -c " samtools view -Sb {}_aligned_minimap.sam > {}_aligned_minimap.bam"
  • 1
    Why do you think this is simpler or less verbose? Since you need 3 chained commands (4 if you count the bash -c script), instead of 1 for loop + 1 command. And in terms of characters it is almost 50% longer.
    – Paul
    Commented Aug 1, 2019 at 8:57
  • less verbose because I have less semi-colons, uppercase characters (which is, in your case, simply convention) and special characters. Though I reckon this is just a matter of taste
    – BCArg
    Commented Aug 2, 2019 at 8:43

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .