Vários arquivos - filtro de comando awk

2

Eu uso um script para dizer; filter1.sh que contém o comando awk;

bzip2 -dc File_1.tsv.bz2 | awk -F '\t' 'BEGIN {OFS=FS} { if (($7) > 50)  print $0 }'  > File_1.tsv

bzip2 -dc File_2.tsv.bz2 | awk -F '\t' 'BEGIN {OFS=FS} { if (($7) > 50)  print $0 }'  > File_2.tsv

para abrir o arquivo bz2 e filtrar os valores da coluna 7 maiores que 50 e gravar a saída em um novo arquivo tsv.

Eu tenho vários arquivos (cerca de 200 que estão localizados em diretórios diferentes) para os quais eu tenho que executar essa etapa de filtragem (note exatamente o mesmo, mas semelhante).

A minha pergunta aqui é como eu passo vários arquivos para este propósito, é possível passar os arquivos através de INFILE separado (como em python).

Algo como:

./filter1.sh pathtofiles.in

na linha de comando. Onde pathtofiles.in contém a localização dos arquivos.

/home/users/gray_wolf/unix/File_1.tsv.bz2
/home/users/gray_wolf/unix/File_2.tsv.bz2
.
.
.
.
.

e assim por diante.

obrigado antecipadamente. ~ M

    
por user3668772 30.07.2015 / 16:17

4 respostas

0

tente

while read f
do
    bzip2 -dc "$f" | 
    awk -F '\t' 'BEGIN{OFS=FS} $7 > 50' > "$(basename "$f" .bz2)"
done < list-of-file.txt
  1. o awk grava o resultado de File_1.tsv.bz2 para File_1.tsv e, portanto, um com File_2, ... File_960.
  2. você informa a lista de arquivos em list-of-file.txt
  3. > $(basename $f .bz2) criará o resultado no diretório local
por 30.07.2015 / 16:29
3

Você pode obtê-los todos em um único fluxo de saída, como:

bzip2 -dc ./File_*.bz2 | filter

Para escrevê-los em arquivos separados, você precisa delimitar o fluxo de alguma forma. Essa seria a solução ideal se você pudesse organizá-la - e com mais informações você poderia obter ajuda para fazê-lo.

Senão você pode chamar seus filtros individualmente uma vez por arquivo de entrada:

for j in ./File_*.bz2
do    [ -f "$j" ] &&
      bzip2 -dc "$j" |
      awk ... >"${j%.*}"
done

Isso não é ideal porque você precisa acessar uma nova instância do seu pipeline por arquivo, mas pode ser uma solução prática para você.

Para obter esse loop de for em outro arquivo de script e, em seguida, para passá-lo, os argumentos com os quais você deseja trabalhar podem ser:

#!/bin/sh
for j do
      case $j in
      (*.bz2) [ -f "$j" ] &&
              bzip2 -dc --  "$j" |
              awk ...   >"${j.*}"
      esac
done

... que é apenas um pouco mais complicado, para que possa garantir que todos os seus argumentos sejam definitivamente nomeados com uma extensão *.bz2 para evitar qualquer inconveniência que possa cercar a transmissão de um argumento sem extensão. arquivo executável chamado ./script em um sistema com um POSIX /bin/sh , ele poderia ser chamado como ...

./script ./File_*.bz2
    
por 30.07.2015 / 16:37
0

No bash, você pode tentar isto:

for f in 'cat $1'
do
  bzip ...
done

Isso pode não funcionar em todos os shells e, sem dúvida, existem outras maneiras de fazer isso. $1 significa "o primeiro parâmetro passado para o script".

    
por 30.07.2015 / 16:21
-1
#!/bin/bash
while read -r j
do 
    [ -f "$j" ] && 
    bzip2 -dc "$j" |
    sed -r '/^([^\t]+\t){6}0*([1-9][0-9]{2,}|[6-9][0-9]|5[1-9])/! d' > "${j%.*}"
done <"$1"
    
por 30.07.2015 / 17:41

Tags