Alguém pode me ajudar com o seguinte problema? Tenho cerca de 40 diretórios de espécies diferentes, cada um com centenas de arquivos de sequência que contêm sequências ortólogas. Os arquivos de sequência são nomeados de forma semelhante para cada um dos diretórios de espécies. Quero concatenar os arquivos com nomes idênticos dos diretórios de 40 espécies em um único arquivo de sequência com nome semelhante.
Por exemplo, tenho os seguintes 3 diretórios: "Species1", "Species2", "Species3". Dentro desses diretórios estão arquivos com nomes semelhantes: "SequenceA.fasta", "SequenceB.fasta", "SequenceC.fasta". Preciso concatenar todo o conteúdo dos diferentes arquivos SequenceA.fasta em um novo arquivo chamado "SequenceA.fasta" em outro diretório. Como eu faço isso?
Eu tentei com o seguinte loop, que falhou. Os arquivos são criados, mas estão vazios:
ls . | while read FILE; do cat ./*/"$FILE" >> ./final/"$FILE"; done
Obrigado por qualquer conselho ou ajuda!
(Desculpe por qualquer postagem cruzada em potencial, postei acidentalmente esta pergunta em um fórum errado anteriormente)
Responder1
Há várias coisas a serem observadas nesta resposta.
Geralmente é uma má ideia analisar a saída
ls
se você pode usarglob
padrões de shell para fazer o que deseja - consulte [http://mywiki.wooledge.org/ParsingLs]. Não usei a opção shell nullglob para portabilidade, mas isso tornaria os scripts um pouco mais curtos.Você quer ter certeza de que seus padrões glob não são muito amplos, então você diz
cat
para usar o mesmo nome de arquivo para entrada e saída. Se fizer isso, você poderá encher seu disco rígido muito rapidamente enquanto tenta criar um arquivo de tamanho infinito.Se você fornecer um padrão semelhante
*.fasta
e ele não corresponder a nenhum arquivo, a string literal*.fasta
será usada.Se você tiver um arquivo chamado
*.fasta
, uma maneira de saber a diferença entre ele e o padrão é ver se ele é legível.Colocar
--
fim à análise de argumentos é uma boa ideia se houver nomes de arquivos não autorizados.
Primeiro um script simples.
# Simple script, assumes that "Species1" has all the needed "SequenceX.fasta" files
# Start in the directory containing "Species1", "Species2" etc.
# create output directory
mkdir "final"
# Go into the first directory
cd "Species1"
# Loop over all the files
for i in *".fasta"
do
# join all the like named files in the sibling directories to the output
# use a pattern which doesn't match ../final/$i to get list of files to join.
cat "../Species"*"/$i" > "../final/$i"
done
Isso pressupõe que "Species1" possui todos os arquivos "SequenceX.fasta". Se este não for o caso, provavelmente você precisará de um loop duplo. Isso é mais robusto, mas mais longo e mais lento.
# Start in the top level and loop over the directories
for dir in */
do
# don't do anything inn the output directory
[ "$dir" = "final" ] && continue
# cd into directory, protecting against rogue directory names
cd "./$dir" || { echo "cd to $dir failed" >&2 ; exit 1 ; }
# loop over the files
for file in *"fasta"
do
# check the file exists, if there are no files matching the pattern
# then the shell will pass the pattern through to the loop
if [ -r "$file" ] ; then
cat -- "$file" >> "../final/$file"
fi
done
cd ".." || { echo "failed to return from $dir" ; exit 1 ; }
done