1

I have 20 files of interest in a directory. They can be split into 5 groups, each group identified by a number from 626 to 630 in the file name. For example, there might (hypothetically) be a file named the-quick-brown-fox-jumps-over-627-lazy-dogs_1_bbduk.fq.

I would like to iterate through each group and temporarily store the paths to the files as text variables (to be used with other commands within the for loop).  This is what I have for now:

for i in {626..630};do
  fw1=$(/scratch/[username]/data/*"$i"-*_1_bbduk.fq)
  fw2=$(/scratch/[username]/data/*"$i"_*_1_bbduk.fq)
  rv1=$(/scratch/[username]/data/*"$i"-*_2_bbduk.fq)
  rv2=$(/scratch/[username]/data/*"$i"_*_2_bbduk.fq)
done

Issue: I get the correct path (there is only one option for each of them), but it says "Permission denied", and I seem unable to use the variable as text later on. It looks like bash is trying to execute it, which is not what I want.

I've tried adding single quotes around (e.g., fw1='$(/scratch/[username]/data/*"$i"-*_1_bbduk.fq)', but that removes the wildcards. I've considered double quotes ( " " ), but I'm not sure how to use them without messing with the "$i" variable. I've tried using echo (e.g., fw1=echo $(/scratch/[username]/data/*"$i"-*_1_bbduk.fq) but that still has the 'permission denied' issue.

1
  • Since you already have the path, which path are you trying to get into each var? Are you refering to the whole filename? Mar 21, 2022 at 16:15

2 Answers 2

4

Bash is trying to execute the filename because you enclose each one in

$( ... )

If that is not what you want, then use:

for i in {626..630}; do
  fw1=/scratch/[username]/data/*"$i"-*_1_bbduk.fq
  fw2=/scratch/[username]/data/*"$i"_*_1_bbduk.fq
  rv1=/scratch/[username]/data/*"$i"-*_2_bbduk.fq
  rv2=/scratch/[username]/data/*"$i"_*_2_bbduk.fq
done

Edit:

Based on your comment, this code may be what you want:

for i in {626..630}; do
  fw1="$(compgen -G /scratch/[username]/data/*"$i"-*_1_bbduk.fq)"
  fw2="$(compgen -G /scratch/[username]/data/*"$i"_*_1_bbduk.fq)"
  rv1="$(compgen -G /scratch/[username]/data/*"$i"-*_2_bbduk.fq)"
  rv2="$(compgen -G /scratch/[username]/data/*"$i"_*_2_bbduk.fq)"
done
1
  • Thank you! It's not quite sufficient because this command seems to remove with the wildcards. For example, adding 'echo "$fw1" ' afterwards as a test gives out stuff like '/scratch/[username]/data/*626-*_1_bbduk.fq', as opposed to, for example, '/scratch/[username]/data/File0626-sequence_1_bbduk.fq'. The wildcards are slightly different for different files so I can't easily account for them.
    – Laura
    Mar 21, 2022 at 15:39
2

Jim correctly identified the problem with your code, but (IMO) a better solution is closer to what you already have:

fw1=(/scratch/username/data/*"$i"-*_1_bbduk.fq)

(note: no $) will give you an array of filenames that match the glob.  The somewhat awkward ${#fw1[@]} will tell you how many elements are in the array.  If, for example, that number is 4, then you can use ${fw1[0]}, ${fw1[1]}, ${fw1[2]} and ${fw1[3]} to access the four elements.  But plain $fw1 will give you ${fw1[0]}, so, if you’re 110% sure that there will be exactly one file matching each pattern, you can just use the short form.

Or, you could say

fw1=$(echo /scratch/username/data/*"$i"-*_1_bbduk.fq)

Again, you were close.  (But the array solution is better if there’s any possibility that there will be more than one file matching the pattern.)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .