john_w
john_w

Reputation: 701

Using basename function during outputting to different file in for loop

I have some questions about using the basename function in bash.

I have some paths stored in a file called filename2.txt, it looks something like this:

/data/sequedas/Miseq2/17031_M0446
/data/sequedas/Miseq2/17022_N0213
/data/sequedas/Miseq2/28103_N3123
...

So I was running a loop trying to do something to each of the folder above:

while read line; 
do interop_imaging_table $line > basename $line ; 
done < filename2.txt

Basically I want to use basename $line to remove everything in the path of the filename except the last part. So that I would be left with the following in the filename by using basename $line:

17031_M0446
17022_N0213
28103_N3123

But unfortunately it doesn't work for some reasons. Basically the output will all output to the file called basename. But I was hoping it would output separately to files called 17031_M0446, 17022_N0213, ....

Upvotes: 0

Views: 1102

Answers (2)

Adam Katz
Adam Katz

Reputation: 16216

Here are two ways to do that.

As a note, I've added some extra quotes to better support any spaces or other unexpected characters in your paths.

First, command substitution:

while read line
  do interop_imaging_table "$line" > "$(basename "$line")"
done < filename2.txt

(Don't worry, the "$(…)" structure allows one level of nested quotes even though SO's syntax highlighting doesn't understand it. I'm not sure if that works with the deprecated "`…`" syntax.)

Second, built-in substitution via parameter expansion:

while read line
  do interop_imaging_table "$line" > "${line##*/}"
done < filename2.txt

"${line##*/}" instructs the shell (bash in your case, but this is POSIX-compliant so it'll work in nearly any shell) to remove characters from the front of the string up to (and including) the final / character. (If you were to say "${line#*/}" then you'd remove characters from the front of the string up to (and including) the first / character.

Similarly, "${line%%/*}" would strip the text from the end up to (and including) the first / character (in this case, you'd end up with empty strings since they start with /). "${line%/*}" is basically the same as "$(dirname "$line")" in that it removes all characters starting with the final /.

To add a suffix to the file name, just add it before the final quote, like "$(basename "$line").txt" or "${line##*/}.txt"

Upvotes: 1

Barmar
Barmar

Reputation: 781994

You have to use $() to substitute the output of a command back into the command line:

interop_imaging_table "$line" > "$(basename "$line")"

What you wrote is equivalent to writing

interop_imaging_table $line $line  > basename

because > just uses the next word as the filename.

You should also remember to quote variables unless you specifically need word splitting to be done on the result.

Upvotes: 0

Related Questions