¿Alguien puede ayudarme con el siguiente problema? Tengo alrededor de 40 directorios de diferentes especies, cada uno con cientos de archivos de secuencia que contienen secuencias ortólogas. Los archivos de secuencia tienen nombres similares para cada uno de los directorios de especies. Quiero concatenar los archivos con nombres idénticos de los directorios de 40 especies en un único archivo de secuencia con un nombre similar.
Por ejemplo, tengo los siguientes 3 directorios: "Especies1", "Especies2", "Especies3". Dentro de estos directorios hay archivos con nombres similares: "SequenceA.fasta", "SequenceB.fasta", "SequenceC.fasta". Necesito concatenar todo el contenido de los diferentes archivos SequenceA.fasta en un archivo nuevo llamado "SequenceA.fasta" en otro directorio. ¿Cómo hago esto?
Lo intenté con el siguiente bucle, que falló. Los archivos se crean pero están vacíos:
ls . | while read FILE; do cat ./*/"$FILE" >> ./final/"$FILE"; done
¡Gracias por cualquier consejo o ayuda!
(Perdón por cualquier posible publicación cruzada, accidentalmente publiqué esta pregunta en el foro equivocado anteriormente)
Respuesta1
Hay varias cosas a tener en cuenta en esta respuesta.
Generalmente es una mala idea analizar la salida de
ls
si, en su lugar, puede usarglob
patrones de shell para hacer lo que quiera; consulte [http://mywiki.wooledge.org/ParsingLs]. No utilicé la opción de shell nullglob para la portabilidad, pero eso haría que los scripts fueran un poco más cortos.Desea asegurarse de que sus patrones globales no sean demasiado amplios, por lo que le indicará
cat
que use el mismo nombre de archivo tanto para la entrada como para la salida; si lo hace, puede llenar su disco duro muy rápidamente mientras intenta crear un archivo de tamaño infinito.Si proporciona un patrón como
*.fasta
y no coincide con ningún archivo,*.fasta
se utiliza la cadena literal.Si tiene un archivo llamado
*.fasta
, una forma de diferenciarlo del patrón es ver si es legible.Poner
--
fin al análisis de argumentos es una buena idea si puede haber nombres de archivos falsos.
Primero un guión sencillo.
# 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
Esto supone que "Species1" tiene todos los archivos "SequenceX.fasta". Si este no es el caso, probablemente necesites un bucle doble. Este es más robusto pero más largo y 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