0

I am trying to iterate through some files in a specific folder to do a specific operation in each of them (using Neuroimaging tool FSL).

When I do

$ find /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/

It returns a list of all the files in that folder

So I did

$  for i in 'find /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/';do /usr/share/fsl/5.0/bin/bet $i ${i}_brain -f 0.4 -g 0;done

But the outcome of that is

Error: input image find not valid

I was able to do this in CentOS 7, so I'd guess that could be the root of the problem...

J. Devez
  • 329
  • 2
  • 6
  • 15

3 Answers3

2

You need a shell glob :

$ for i in /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/*; do 
    bet "$i" "${i}_brain" -f 0.4 -g 0
done
Gilles Quénot
  • 173,512
  • 41
  • 224
  • 223
0

Use the -exec option to find:

find /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/ -exec /usr/share/fsl/5.0/bin/bet {} {}_brain -f 0.4 -g 0 \;

For those who prefer their code spread out over multiple lines:

find /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/ \
    -exec /usr/share/fsl/5.0/bin/bet {} {}_brain -f 0.4 -g 0 \;

Example

Suppose we have a directory with these files:

$ find .
.
./dir1
./dir1/file2
./dir1/file1

We can run an echo command on each of these files that shows that the file names are substituted correctly into a command:

$ find . -exec echo bet {} {}_brain -f 0.4 -g 0 \;
bet . ._brain -f 0.4 -g 0
bet ./dir1 ./dir1_brain -f 0.4 -g 0
bet ./dir1/file2 ./dir1/file2_brain -f 0.4 -g 0
bet ./dir1/file1 ./dir1/file1_brain -f 0.4 -g 0

If you only want your command run on regular files, not directories, then add the -type f test:

$ find . -type f -exec echo bet {} {}_brain -f 0.4 -g 0 \;
bet ./dir1/file2 ./dir1/file2_brain -f 0.4 -g 0
bet ./dir1/file1 ./dir1/file1_brain -f 0.4 -g 0
John1024
  • 109,961
  • 14
  • 137
  • 171
0

Your script should work with the following adjustments:

IFS=$'\n' for i in $(find /home/Desktop/MSc/ImagensMRI/T1/t1inciais/t1alzheimer/)
do 
  /usr/share/fsl/5.0/bin/bet "$i" "${i}_brain" -f 0.4 -g 0
done

The $(...) syntax is for starting find as a separate command, instead of creating a string literal 'find ... '.

The IFS is the separator that splits results returned by find. We have to update it, because otherwise pieces of filenames with whitespace will be assigned to i separately.

This answer here explains why the $ in IFS=$'\n' is necessary.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • Missing double quotes around all variables. No problem with files with space in her names if well quoting – Gilles Quénot Feb 27 '18 at 01:47
  • @GillesQuenot As I said: one-off script that is supposed to work under the assumption that all file names are benign. The OP used `$i` without quotes, therefore I assume that the files are named something like `mriscan00001.png` to `mriscan12345.png`. But yes, you are right, it's very brittle. Veeery brittle. – Andrey Tyukin Feb 27 '18 at 01:49
  • Not a good reason to not quote them every times (apart for int values) – Gilles Quénot Feb 27 '18 at 01:50
  • @GillesQuenot This should be slightly better, I hope? Or will the IFS do something funny? – Andrey Tyukin Feb 27 '18 at 01:55
  • Yes, better now. No need IFS – Gilles Quénot Feb 27 '18 at 01:56
  • @GillesQuenot it didn't work without the IFS part if the names had spaces in them, it used every space-separated piece of filename as `i`. I can't say right away what the `$` after the IFS is good for, if I remember correctly it had something to do with `'\\n'` behaving strangely otherwise. Searching some doc about this... Thanks for constructive feedback ;) – Andrey Tyukin Feb 27 '18 at 02:00