Copying specific file types to specific folders

I am trying to write a script that cycles through a folder containing many folders and when inside each one it's supposed to copy all the .fna.gz files to a folder elsewhere if the file and the respective folder have the same name.

for fldr in /home/playground/genomes/* ; do

    find . -name *fna.gz | while read f ; do

        f_name=$( echo $fldr | cut -d '/' -f 7 | cut -d '_' -f 1) ;

        #echo $f_name ;

        if [ "$f_name" == /home/playground/port/"$f_name" ]; then

        cp -r "$f" /home/playground/port/"$f_name"/ ;

        else

        continue    

        fi

    done

done

This script so far doesn't actually copy anything over at all.

Your script doesn't copy anything because

f_name=$( echo $fldr | cut -d '/' -f 7 | cut -d '_' -f 1) 

results in a null value, at least is does if you are using the expansion

/home/playground/genomes/*

Andrew

f_name 

is supposed to be the name, so it's used as a reference point because these files are something like "Long_John_Silver" but the folders into which they're supposed to be placed are like "Long".

Also note, that this if statement will never be true:

 if [ "$f_name" == /home/playground/port/"$f_name" ]; then

Perhaps you meant:

 if [ "$f" == /home/playground/port/"$f_name" ]; then

Remember I showed you this construct: basenm=${fldr##*/} followed by f_name=${basenm%%_*} in this thread for extracting the filename proceeding _ from a full path.

This trick should server you well in this script to replace the echo + double cut command substitution.

This is what I have now, but still no success.

 

cd /home/scripts/playground/genomes_2 ;

for fldr in /home/scripts/playground/genomes_2/* ; do

    find . -name *fna.gz | while read f ; do

        #f_name=$( echo $fldr | cut -d '/' -f 7 | cut -d '_' -f 1) ;

        basenm=${fldr##*/} ; f_name=${basenm%%_*} ; 

        #echo $f_name ;

        if [ "$f" == /home/scripts/playground/port/"$f_name" ] ; then

        cp $f /home/scripts/playground/port/"$f_name"/ ;

        else

        continue    

        fi

    done

done

I'm losing the plot here. Could you please show an example or two of:

  1. $fldr;
  2. $f_name;
  3. $f

One of the problems I'm having is that if $fldr has values such as

  • long_john_silver
  • jack_of_lantern
  • nick_swift

then f_name will have values like

  • long
  • jack
  • nick

and yet you appear to be looking for values of $f_name that match $f and therefore end in fna.gz . That is not going to work. Perhaps if the line

if [ "$f" == /home/scripts/playground/port/"$f_name" ] ; then

was actually

if [ "${f%fna.gz}" == /home/scripts/playground/port/"$f_name" ] ; then

you may stand a better chance? But without looking at actual names you are trying to match we can't tell you why your code doesn't work.

Andrew

2 Likes

I realised that I was copying all the files into all the folders based on the type of file i.e. .fna.gz, so I specified what type of fna.gz file I want to be read and then copied. There is no need for an if statement since the specificity is implied through the parameter expansion. It now works perfectly.

 
 
    for fldr in /home/scripts/playground/genomes_2/* ; do

    basenm=${fldr##*/} ; f_name=${basenm%%_*} ; 

    find . -name $f_name*fna.gz | while read f ; do

        cp -r $f /home/scripts/playground/port/$f_name/ ;

    

    done

    done

Why the -r option to the cp command?

Good shout, it's not needed since I'm not copying folders. I think it's a bad habit of mine since I tend to copy folders around a lot.