将更多文件以相似的名称放在一个目录中

Cat more files together in a directory by similar names

我在同一目录下有如下五个文件(名称以.bed and startchromosomeand have numbers such as1-5`结尾嵌入中间;显示一行内容或每个文件) :

染色体 1-5.bed

chromosome1     1   21

染色体 1-2.bed

chromosome1     7   30

染色体 1-9.bed

chromosome1     9   75

染色体 2-1.bed

chromosome2     8   50

染色体 2-5.bed

chromosome2     6   23

并且我尝试将以相同编号开头的文件分类为一个文件(因此所有在 1-5 等中以 1 开头的文件)。

预期输出:

染色体1.bed

chromosome1     1   21 
chromosome1     7   30
chromosome1     9   75

染色体2.bed

chromosome2     8   50 
chromosome2     6   23

此时我尝试将目录中的任何文件与另一个具有文件名的文件进行比较。

for i in /dir/*; do
    for j in /dir/*; do
        filename=$(basename "$i")
        filename2=$(basename "$j")
        if "$filename" != "$filename2";
        then cat "$i" "$j" > newfile
        fi
    done
done 

为什么不使用 globbing?

cat chromosome1-* >> chromosome1.bed

cat chromosome2-* >> chromosome2.bed

chromosome2-* 将 select 所有以 chromosome2- 开头的文件,如果您有太多手动操作,您可以将它放在每个索引的循环中。

awk '!/^---/ {fname= ".bed"; print [=10=] > fname }' *-[0-9].bed

输出

cat chromosome1.bed

chromosome1     7   31
chromosome1     1   21
chromosome1     9   75


cat chromosome2.bed

chromosome2     8   50
chromosome2     6   23

此脚本跳过以 ---- 开头的行,并从剩余数据行的第一个字段创建文件名。我们将 ".bed" 附加到该名称,然后将完整的行写入 (>) 到命名文件。随着 </code> 值的变化,文件名也会发生变化。</p> <hr> <p><strong>编辑</strong></p> <p>由于您修改后的示例数据不再包含 <code>------ 行,因此可以进一步简化为

awk '{fname= ".bed"; print [=12=] > fname }' *-[0-9].bed

不需要过滤行 ---- 并且该测试已被删除。所有行现在将自动打印到基于第一个字段创建的文件名中。


编辑 2

要允许将文件写入备用目录,一种方法是将目录名称作为变量传递,并将其预先附加到正在创建的 fname,即

awk -v dir="NewDirectory" '{fname= dir "/"  ".bed"; print [=13=] > fname }' *-[0-9].bed

而且,当然 "NewDirectory" 可能类似于 "$i/$j"

IHTH

虽然我喜欢 awk 解决方案 shelter,但 make 是另一种选择。这是 GNU make 的版本:

SRC = $(wildcard chromosome*-*.bed)
TGT = $(sort $(shell echo $(SRC) | sed -E 's/-[0-9]+[.]bed/.bed/g'))

all: $(TGT)

$(TGT): $(SRC)
    cat $(subst .bed,-*.bed,$@) > $@~
    mv $@~ $@

echo: 
    @ls $(SRC)
    @echo targets: $(TGT)

上面的每个目标都依赖于每个源,这显然是矫枉过正。如果您有很多文件或它们经常更改,您可能希望生成正确的依赖项。

优点:

  • 可以通过说例如make chromosome2.bed
  • 如果没有更改或添加文件,则跳过重新生成。
  • 错误停止,生成的文件不会部分完成。

输出:

$ make
cat chromosome1-*.bed > chromosome1.bed~
mv chromosome1.bed~ chromosome1.bed
cat chromosome2-*.bed > chromosome2.bed~
mv chromosome2.bed~ chromosome2.bed

$ head  chromosome?.bed
==> chromosome1.bed <==
chromosome1     7   30
chromosome1     1   21
chromosome1     9   75

==> chromosome2.bed <==
chromosome2     8   50
chromosome2     6   23