Maria A Sierra
Maria A Sierra

Reputation: 31

Rename files matching pattern in a loop - Bash

I have been trying to rename some specific files based on a table but with no success. It either renames all files or gives error.

The directory contains hundreds of files named with long barcodes and I want to rename only files containing the patter _1_.

Example

barcode_1_barcode_SL484171.fastq.gz   barcode_2_barcode_SL484171.fastq.gz   barcode_1_barcode_SL484370.fastq.gz   barcode_2_barcode_SL484370.fastq.gz

mytable.txt

oldname newname
barcode_1_barcode_SL484171 Description1
barcode_2_barcode_SL484171 Description1
barcode_1_barcode_SL484370 Description2
barcode_2_barcode_SL484370 Description2

Desire output:

Description1.R1.fastq.gz Description2.R1.fastq.gz

As you can see in the table there are two files per description but I only want to rename the ones with the _1_ pattern.

Code I have tried:

for i in *_1_*.fastq.gz; do read oldname newname; mv "$oldname" "$newname".R1.fastq.gz; done < mytable.txt

for i in $(grep '_1_' mytable.txt); do read -r oldname newname; mv ${oldname} ${newname}.R1.fastq.gz; done < mytable.txt

for i in $(grep '_1_' mytable.txt); do oldname=$(cut -f1 $i);newname=$(cut -f2 $i); ln -s ${oldname} ${newname}.R1.fastq.gz; done

Upvotes: 3

Views: 1046

Answers (2)

Jetchisel
Jetchisel

Reputation: 7781

Something like this.

#!/usr/bin/env bash

while IFS= read -r files; do                 ##: loop through the output of `grep 'barcode_1_barcode.*' table.txt`
  while read -ru9 old_name prefix; do        ##: loop through the output of `find . -name 'barcode_1_barcode*.gz' | grep -f <(cut -d' ' -f1 table.txt`
    if [[ $files == *"$old_name"* ]]; then   ##: If the filename from the output of find matches the first field of table.txt (space delimite)
      old_filename="${files%.fastq.gz}"      ##: Extract the filename without the fast.gz extesntion
      extension="${files#"$old_filename"}"   ##: Extract the extention .fast.gz without the filename
      # mv -v "$files" "$prefix.R1${extension}"
      printf '%s %s %s ==> %s\n' mv -v "$files" "$prefix.R1${extension}"  ##: Rename the files to the desired output
    fi
  done 9< <(grep 'barcode_1_barcode.*' table.txt)
done < <(find . -name 'barcode_1_barcode*.gz' | grep -f <(cut -d' ' -f1 table.txt) ) ##: Remain the first column/field of table.txt

Output from the OP's sample data/files.

renamed './barcode_1_barcode_SL484370.fastq.gz' -> 'Description2.R1.fastq.gz'
renamed './barcode_1_barcode_SL484171.fastq.gz' -> 'Description1.R1.fastq.gz'

  • If you're satisfied with the output either move the # from the front of mv to the

    front of printf or just delete the entire line with printf and remove the # from

    mv in order for mv to actually rename the files.

Upvotes: 2

Kyle Banerjee
Kyle Banerjee

Reputation: 2784

while read -r oldname newname
do 
    if [[ $oldname =~ "_1_" ]]
    then 
        mv $oldname $newname
    fi
done < mytable.txt

Upvotes: 2

Related Questions