通过与通配符和下划线组合扩展Bash循环脚本中的索引

时间:2017-05-08 16:27:58

标签: bash loops escaping wildcard

我有80对以下类型的文件:

170309-N701-S517_S1_L001_R1_001.fastq.gz
170309-N701-S517_S1_L001_R2_001.fastq.gz
170309-N701-S502_S2_L001_R1_001.fastq.gz
170309-N701-S502_S2_L001_R2_001.fastq.gz
170309-N701-S503_S3_L001_R1_001.fastq.gz
170309-N701-S503_S3_L001_R2_001.fastq.gz
..
170309-N710-S507_S79_L001_R1_001.fastq.gz
170309-N710-S507_S79_L001_R2_001.fastq.gz
170309-N710-S508_S80_L001_R1_001.fastq.gz
170309-N710-S508_S80_L001_R2_001.fastq.gz

基本上,一对由以下文件组成:

170309-N701-S517_S<ID>_L001_R1_001.fastq.gz
170309-N701-S517_S<ID>_L001_R2_001.fastq.gz

其中ID从1到80不等。

我想创建80个名为S1..S80的子文件夹,并将每一对放在相应的文件夹中,例如

170309-N701-S517_S1_L001_R1_001.fastq.gz
170309-N701-S517_S1_L001_R2_001.fastq.gz

转到子文件夹S1

170309-N701-S502_S2_L001_R1_001.fastq.gz
170309-N701-S502_S2_L001_R2_001.fastq.gz

转到子文件夹S2

等等。

我写了以下脚本:

#!/bin/bash
for i in {1..80}
do
   mkdir S$i
   mv "*_S"$i"_*" S$i
done

但它没有按预期工作。它创建了子文件夹S1..S80。但是,它没有移动任何文件。它产生了

mv: cannot stat `*_S1_*': No such file or directory
mv: cannot stat `*_S2_*': No such file or directory

等等。

我做错了什么?你能纠正这个剧本吗?

1 个答案:

答案 0 :(得分:2)

您尝试使用mv "*_S"$i"_*" S$i行的内容称为variable expansion,如果您作为扩展的一部分想要将变量与其他字符连接起来,则需要让BASH知道什么是变量,什么是普通字符。您可以通过将变量名称括在花括号中来完成此操作。 E.g:

var=FOO
echo "BAR ${var} BAZ"
# BAR FOO BAZ

对于你的循环:

touch \
  170309-N701-S517_S1_L001_R1_001.fastq.gz\
  170309-N701-S517_S1_L001_R2_001.fastq.gz\
  170309-N701-S502_S2_L001_R1_001.fastq.gz\
  170309-N701-S502_S2_L001_R2_001.fastq.gz\
  170309-N701-S503_S3_L001_R1_001.fastq.gz\
  170309-N701-S503_S3_L001_R2_001.fastq.gz

for i in {1..80}
do
if test -n "$(find . -maxdepth 1 -name "*_S${i}_*" -print -quit)"
then
   mkdir "S${i}"
   mv *"_S${i}_"* "S$i"
fi
done

if-then-fi位只是为了避免为不存在的文件创建目录。完全可选。

另请注意,为了与*合作,必须使用未加引号的字符串mv,因为在"..."'...'内,{ {1}}被视为文字 但是在*命令中可以看到一个例外,其中双引号之间的内容将在传递给find时进行扩展。为了避免在这种情况下的扩展,参数可以包含在引号(find