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

问题描述 投票:1回答:1

我有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

等等。

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

bash loops escaping wildcard
1个回答
2
投票

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

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,因为在"..."'...'中,*被视为文字。 然而,在find命令中可以看到一个例外,其中双引号之间的内容将在传递给find时进行扩展。为了避免在这种情况下的扩展,参数可以用单引号括起来('...'

© www.soinside.com 2019 - 2024. All rights reserved.