我试图将文件名一部分的数字存储为变量,以便我可以通过循环一次更改和重命名一堆文件。文件名是trimmed-barcode*.1.fastq.gz,其中*是一个可变的两位或三位数字,我想将其保存为num。这将允许我将 $num 乘以我之前定义的 $number 变量,并用相乘的数字重命名每个文件(但现在我只是用 echo 测试它)。如何存储文件名中的两位或三位数?
for infile in trimmed-barcode*.1.fastq.gz
do num= #how do I get this number
num2=$(($num * $number))
echo "trimmed-barcode${num2}.1.fastq.gz"
done
答案1
如果您使用bash
脚本,您可以从字符串中提取两个数字。例如
var="abcdefg"
echo "${var:3:2}" # Outputs "de"
有了这个,我们就可以像这样调整你的脚本
#!/bin/bash
for infile in trimmed-barcode??.1.fastq.gz
do
num="${infile:15:2}" # Two characters starting at position 15
result=$(( ${num#0} * number ))
echo "trimmed-barcode$result.1.fastq.gz"
done
在相乘时$num
,$number
我们必须从值中去除任何前导零,这样bash
就不会尝试将其视为八进制。就是这样${num#0}
。
您已将问题修改为询问两个或三个数字。这显着改变了实现。
您可以重复循环,但这次匹配三个数字:
for infile in trimmed-barcode??.1.fastq.gz do # Code as above for two digit extracts done for infile in trimmed-barcode???.1.fastq.gz do # Modify code as above to process three digit values done
您可以更改代码以删除不变的部分,假设剩下的内容一定是感兴趣的值:
for infile in trimmed-barcode*.1.fastq.gz do num=${infile#trimmed-barcode} # Strip leading text num=${num%.1.fastq.gz} # Strip trailing text result=$(( ${num#0} * number )) echo "trimmed-barcode$result.1.fastq.gz" done
答案2
for file in trimmed-barcode*.1.fastq.gz; do
x=${file#trimmed-barcode}
num=${x%.1.fastq.gz}
echo "$file: $num"
done
或者在 Bash 中,您可以使用正则表达式匹配来选择文件名的所需部分:
for file in trimmed-barcode??.1.fastq.gz; do
[[ $file =~ trimmed-barcode(.*)\.1\.fastq\.gz ]]
num=${BASH_REMATCH[1]};
echo "$file: $num"
done
或者,如果您想修剪它,只需选择第一个点之前的两个字符[[ $file =~ (..)\. ]]
。
答案3
要将文件名中的两位数字存储为循环中的变量,可以在 bash 中使用文件名扩展和字符串操作。这是一个例子:
for infile in trimmed-barcode*.1.fastq.gz
do
num="${infile:14:2}"
num2=$((num * number))
echo "trimmed-barcode${num2}.1.fastq.gz"
done
在此代码中,我们使用 ${infile:14:2} 字符串扩展从文件名中提取从索引 14 开始的两位数。然后将该数字 (num) 乘以 $number 变量并将结果存储在编号2。最后,我们用修改后的数字回显生成的文件名。
请记住根据文件名中数字的实际位置调整索引(在本例中为 14)。
答案4
以下使用 perlrename
实用程序:
注意:perlrename
也称为file-rename
、perl-rename
、 或prename
,具体取决于您的发行版。不要将其与具有完全不同且不兼容的功能和命令行选项的rename
实用程序混淆。 util-linux
Perl 重命名允许您使用任意复杂的 Perl 代码来重命名文件,但最常用于对文件名执行简单的类似 sed 的 s/search/replace/ 操作。
首先创建一些文件名进行测试:
for i in 11 234 56 789 ; do touch "trimmed-barcode$i.1.fastq.gz" ; done
然后重命名它们:
export number=2
rename -n 's/^(trimmed-barcode)(\d{2,3})(\.1\.fastq\.gz)$/$1 . $2 * $ENV{number} . $3/e' trimmed*
示例输出:
rename(trimmed-barcode11.1.fastq.gz, trimmed-barcode22.1.fastq.gz)
rename(trimmed-barcode234.1.fastq.gz, trimmed-barcode468.1.fastq.gz)
rename(trimmed-barcode56.1.fastq.gz, trimmed-barcode112.1.fastq.gz)
rename(trimmed-barcode789.1.fastq.gz, trimmed-barcode1578.1.fastq.gz)
该-n
选项使其成为一次试运行,因此它仅显示它的内容会做。要实际重命名文件,请删除-n
或将其替换-v
为详细输出。
该$number
变量必须导出到环境中,以便rename
脚本可以通过哈希访问它%ENV
。或者,您可以在同一命令行上分配变量(例如number=2 rename -n '...' trimmed*
(具有为该命令临时导出变量的效果)或将其硬编码到脚本中。
要使其适用于 之前的任意数量的数字(即一位或多位),.1.fastq.gz
请将 更改\d{2,3}
为\d+
。
要使其适用于数字之前的任何文件名前缀(不仅仅是“修剪条形码”)以及第一个之后的任何扩展名.
,请将其更改为:
rename -n 's/(.*?)(\d{2,3})(\..*)/$1 . $2 * $ENV{number} . $3/e' trimmed*
该脚本利用 Perl 的功能,使用/e
正则表达式修饰符在替换运算符的右侧(替换)部分执行 Perl 代码s///
。在本例中,.
是 perl 的字符串连接运算符,因此代码将第一个捕获组 ( $1
) 与第二个捕获组 ( $2
) 乘以$number
环境变量以及第三个捕获组 ( $3
) 连接起来。
顺便说一句,perlrename
不会覆盖现有文件,除非您使用-f
/--force
选项强制它。
与替换运算符左侧(搜索)部分的正则表达式不匹配的文件名将不会以任何方式重命名或修改。