Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Bash循环脚本中结合使用通配符和下划线展开索引_Bash_Loops_Escaping_Wildcard - Fatal编程技术网

在Bash循环脚本中结合使用通配符和下划线展开索引

在Bash循环脚本中结合使用通配符和下划线展开索引,bash,loops,escaping,wildcard,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

我有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
转到子文件夹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
等等


我做错了什么?您能更正脚本吗?

调用
mv“*\u S”$i“\u*”S$i
行时,如果作为扩展的一部分,您希望将变量与其他字符连接起来,则需要让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
如果fi位存在,只是为了避免为不存在的文件创建目录。完全可选

还要注意的是,为了处理
mv
,必须使用全局字符
*
,因为在
“…”
“…”
中,
*
被视为一个文本。

但是,在
find
命令中可以看到一个例外,在该命令中,双引号之间的内容将在传递到
find
时展开。要避免在这种情况下展开,参数可以用单引号括起来(
“…”

Globs不能用引号展开,请删除引号。您的下划线会导致搜索出现问题,因为它们不在引号内,需要转义。行应该
mv*\\\\\\\\\\\\*
删除引号后,您需要像
${i}
中那样用
${i}
包围变量,否则它将查找名为
$i\/code>@jneville的变量下划线不需要转义,问题是,正如ccarton所提到的,它试图扩展
$i
。用
{}
正确地扩展变量是正确的解决方案。@CharlesDuffy:我认为这个问题不应该作为一个重复来解决。当然,这里的答案与链接中的答案相似,但问题并非如此,因此per不是傻瓜。就我所见,这个问题最大的缺点是标题太不具体。要清楚,只有当紧跟其后的字符(如下划线)在shell变量名中有效时,这才是必要的。
find
在性能方面有点昂贵,这意味着使用两种不同的glob机制(
find
)就在那里,shell后面几行是用于
mv
——如果您启用了shell extglobs和一个更有趣的glob表达式,它们可能不匹配)。我建议
匹配=(*_s“$I”*);如果[[-e${matches[0]}|-L${matches[0]];然后…
以避免外部命令启动成本,并确保您可以
mv“${matches[@]}”S$i
稍后,重复使用单个glob操作的结果,而不是重新计算它。@CharlesDuffy:如果我从头开始编写这个例程,它看起来会很不一样。我发布的是一个最小的改进。为了捍卫完美主义,我们在这里建立了一个教育资源;一个答案的生命远远超过了操作It最初是为了它而写的。
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