Concatena arquivos em vários subdiretórios correspondentes

2

Eu preciso concatenar arquivos com base no nome do subdiretório em que estão. Os subdiretórios às vezes têm duplicatas e outras vezes não. A estrutura do arquivo é assim:

  1. RootDir
    • 633
      • 633_S1_L001_R1_001.fastq
      • 633_S1_L001_R2_001.fastq
    • 739
      • 739_S1_L001_R1_001.fastq
      • 739_S1_L001_R2_001.fastq
    • 739 (1)
      • 739_S1_L001_R1_001.fastq
      • 739_S1_L001_R2_001.fastq
    • 739 (2)
      • 739_S1_L001_R1_001.fastq
      • 739_S1_L001_R2_001.fastq
    • 834
      • 834_S3_L001_R1_001.fastq
      • 834_S3_L001_R2_001.fastq
    • 834 (1)
      • 834_S7_L001_R1_001.fastq
      • 834_S7_L001_R2_001.fastq

É o prefixo de 3 números e o número-R que importa, e o concat deve ser feito em R # correspondentes, com o número S sendo variável.

  1. Nenhuma concatenação precisaria ser feita nos arquivos em dir 633
  2. Todos os 3 arquivos R1 nos 739 dirs precisariam ser concatenados em ordem (739 primeiro, 739 (1) ...)
  3. A saída precisaria ir para um subdiretório do subdir (/ RootDir / 739/739 / *)
  4. No final, cada dir de saída final teria um arquivo R1 concatenado e um arquivo R2.

Eu apreciaria muito qualquer ajuda na direção certa. Observe também que os arquivos .fastq são simplesmente arquivos ASCII txt.

edit: eu vi este post um pouco relacionado , mas não tiveram sucesso em usar o código devido ao problema com várias pastas correspondentes.

edit2: Nenhuma dessas soluções está funcionando para mim. Estou lentamente combinando idéias que ambos me deram e postarei minha eventual solução aqui.

    
por Carpe_Noctem 08.10.2013 / 22:02

3 respostas

2

de acordo com o seu exemplo, qualquer diretório que tenha "duplicatas" tenha uma terminação duplicada em "(1)", portanto:

for dir in ???\(1\)/; do 
    base=${dir%(*}
    for i in 1 2; do
        f=${base}_S1_L001_R${i}_001.fastq
        echo "mv ${base}/$f ${base}/$f.bak"
        echo "cat ${base}*/${f}* > ${base}/$f"
    done
done

Remova os "echo" quando estiver pronto

    
por 08.10.2013 / 23:20
0

Não há uso para nenhuma ferramenta de processamento de texto diferente de cat , já que tudo o que você está fazendo com o conteúdo do arquivo é concatená-las.

Começamos no RootDir. Eu suponho que em NNN (K), K ≤ 999999999, e K é escrito sem levar 0. Eu construo os padrões com ([0-9]) , ([0-9][0-9]) , etc., de modo a concatenar NNN (9) antes de NNN (10 ).

pattern_prefix='[0-9][0-9][0-9]([1-9]'
while [ ${#pattern_prefix} -le 13 ]; do
  # Iterate over the NNN(K) directory where K has a certain number of digits
  for dir in $pattern_prefix\); do
    if ! [ -d "$dir" ]; then break; fi
    base=${dir%\(*}
    target=$base/$base
    # If this is the first NNN(K) directory we meet for this NNN, create the base
    if [ ! -d "$target" ]; then
      mkdir "$target"
      cp -p "$base/"*.fastq "$target"
    fi
    # For each file in NNN(K), determine the target file and append
    for f in "$dir/"*.fastq; do
      stem=${f##*/}; stem=${f#*_*_}
      set -- "$target/"*_*_"$stem"
      cat "$f" >>"$1"
    done
  done
  pattern_prefix=$pattern_prefix'[0-9]'
done
    
por 09.10.2013 / 02:24
0

Se eu estou entendendo a pergunta corretamente, você quer algo assim:

for D in ???
do
  [[ -d $D?* ]] || continue
  mkdir $D/$D
  for F in $D/*
  do
    cat $D*/$F > $D/$D/$F
  done
done

Isso não assume espaços no diretório de nomes de arquivos e que todos os arquivos duplicados aparecerão pelo menos no diretório de 3 caracteres. Se você tiver um nome de arquivo que esteja apenas nos diretórios 111 (1), substitua

  for F in $D/*

com

  for F in $( find $D* -printf "%f\n" | sort -u )

para obter uma lista de nomes exclusivos em 111, 111 (1), etc.

    
por 11.10.2013 / 23:30