简体   繁体   中英

Bash - Move files that contain certain string

I have two folders: Controls and Patients . Inside each one of these there are several folders for different individuals ( CO1 , CO2 ), with this organization:

   Controls

   └───C01
   │   └───ROIS 
   │       └───rs_rois (imgs inside)
   │   └───Cortical_masks
   │       └─── accumbens
   │       └─── putamen
   │       └─── caudatus
   │   
   └───C02
   │   └───ROIS 
   │       └───rs_rois (imgs inside)
   │   └───Cortical_masks
   │       └─── accumbens
   │       └─── putamen
   │       └─── caudatus

And the same for Patients

I want to move the imgs from rs_rois to Cortical_masks folder based on a substring of their names. So for example L_accumbens_rsfmri file should go to accumbens folder and R_caudate_rsfmri should go to caudate folder.

This is what I have:

#!/bin/bash
DIR="/media/roy"; cd "$DIR/Analysis" || exit
for group in Controls Patients; do
    for case in "$group"/*; do
        for file in $DIR/Analysis/$case/ROIS2/rs_roi/*; do
            if grep -q accumbens "$file"; then
                mv $file $DIR/Analysis/$case/Cortical_masks/accumbens
            elif grep -q putamen "$file"; then
                mv $file $DIR/Analysis/$case/Cortical_masks/putamen
            elif grep -q caudate "$file"; then
                mv $file $DIR/Analysis/$case/Cortical_masks/caudate
            fi
        done;
    done;
done;

This script doesn´t do anything, why is that? If I add some echo statements, I can see that the for file loop goes through all my files, but the code never gets to the mv statements.

The problem is that the grep expression you use looks for the string ( accumbens , etc) in the contents of the file instead of in the name of the file.

Replace each grep by a pattern match like if [[ $file =~ accumbens ]] ...

The script then becomes:

#!/bin/bash
DIR="/media/roy"; cd "$DIR/Analysis" || exit
for group in Controls Patients; do
    for case in "$group"/*; do
        for file in $DIR/Analysis/$case/ROIS2/rs_roi/*; do
            if [[ $file =~ accumbens ]]; then
                mv $file $DIR/Analysis/$case/Cortical_masks/accumbens
            elif [[ $file =~ putamen ]]; then
                mv $file $DIR/Analysis/$case/Cortical_masks/putamen
            elif [[ $file =~ caudate ]]; then
                mv $file $DIR/Analysis/$case/Cortical_masks/caudate
            fi
        done;
    done;
done;

Use find .

#!/bin/bash
cd /path/to/Analysis/
for group in Control Patients; do
  for case in "$group"/*; do
    orig="$group/$case/ROIS/rs_rois"
    dest="$group/$case/Cortica_masks"
    find "$orig" -type f -name '*accumbens*' -exec mv {} "$dest" \;
    find "$orig" -type f -name '*putamen*' -exec mv {} "$dest" \;
    find "$orig" -type f -name '*caudate*' -exec mv {} "$dest" \;
  done
done

This is a clear way that doesn't need string comparations.

Would something like this work?

make a file.txt containing the strings you want

cat file.txt

caudate

putamen

Then

while read p; do mv $p $DIR/Analysis/$case/Cortical_masks/${p} done < file.txt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM