como colar parte do nome do arquivo para o conteúdo do arquivo?

5

Eu tenho uma pasta com 1000 arquivos; todos os caracteres antes de mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp referem-se ao ID do indivíduo (por exemplo, NA21117, NA21119, NA21126, ..)

NA21117.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21119.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21126.mapped.ILLUMINA.bwa.GIH.low_coverage.20121211.bam_dp
NA21127.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21137.mapped.ILLUMINA.bwa.GIH.low_coverage.20120522.bam_dp
NA21142.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
NA21143.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp

Cada arquivo tem apenas uma linha:

cat NA21143.mapped.ILLUMINA.bwa.GIH.low_coverage.20130415.bam_dp
1   115258827   10

para cada um desses arquivos, quero colar o ID individual no conteúdo do arquivo e obter uma saída como:

1   115258827   10 NA21143

Existe alguma maneira de fazer isso?

    
por Anna1364 02.05.2018 / 20:55

4 respostas

2

Use um loop:

#!/bin/bash

shopt -s nullglob
for file in ???????.mapped.*bam_dp; do
  [[ -f "$file" ]] || continue
  id=${file%%.*}              # grab the ID from file name
  sed -i "s/$/ $id/" "$file"  # modify the file in-place
done
    
por 02.05.2018 / 21:02
4

plain bash

for file in *.bam_dp; do 
    contents=$(< "$file")
    echo "$contents ${file%%.*}" > "$file"
done

para arquivos multi-line, ainda pode ser feito com o bash simples

for file in *.bam_dp; do 
    mapfile -t contents < "$file"
    printf "%s\n" "${contents[@]/%/ ${file%%.*}}" > "$file"
done

notas:

  • o comando mapfile lê o arquivo em uma matriz de linhas.
  • a expansão do parâmetro ${var/pattern/string} faz uma pesquisa e substituição no valor da variável. (documentado no manual )
    • se o padrão começar com % , o padrão será ancorado no final da string. Aqui, eu estou combinando o padrão vazio no final da string.
    • a variável pode ser uma expansão de matriz, caso em que a substituição ocorre para cada elemento da matriz.

Francamente, essa abordagem é inteligente demais, e eu gostaria de algo mais óbvio.

    
por 02.05.2018 / 21:51
2

Remover. * de $ ARGV, em seguida, acrescente \ t $ ARGV ao arquivo:

perl -i -pe '$ARGV=~s/\..*//; s/$/\t$ARGV/;' NA*

A solução de Glenn provavelmente será mais rápida de executar:

perl -i -lpe '$_ .= " " . substr($ARGV,0,index($ARGV,"."))' NA*

embora se cada arquivo é apenas uma única linha, a maior parte do tempo estará procurando na unidade.

    
por 02.05.2018 / 21:13
1

awk

Este método é compatível com as versões GNU (Linux) e BSD (Mac) de awk .

awk '{ id=FILENAME ; sub(/\..*/,"",id) ; print $0 "\t" id }' *.bam_dp
  • id=FILENAME ; sub(/\..*/,"",id)
    Armazena a primeira parte de cada *.bam_dp filename (tudo antes do primeiro . ) como id .
  • print $0 "\t" id
    Imprima o conteúdo de cada arquivo, em seguida, um caractere de tabulação e, em seguida, o registro id .

Isto irá imprimir uma lista com linhas como no seu exemplo:

1   115258827   10 NA21143

Os arquivos originais não serão modificados. Você pode salvar essa saída, por exemplo, adicionando > file.txt ao final do comando.

    
por 02.05.2018 / 21:56