ubuntuusers.de

Find und dann cp Befehl optimieren

Status: Ungelöst | Ubuntu-Version: Ubuntu 20.04 (Focal Fossa)
Antworten |

SK-N-BE

Anmeldungsdatum:
14. Juni 2018

Beiträge: 120

Moin, ich schreibe gerade ein Skript, das von vorne bis hinten super funktioniert und genau das tut, was es soll. An einer Stelle kommt aber immer die Meldung,dass zwei Dateien dieselben sind. Es stört nicht das "Ergebnis" der Pipeline aber irgendetwas scheint ja nicht ganz richtig zu sein, sonst würde die Meldung nicht kommen.

Ich habe an der Stelle folgendes:

1
2
3
4
5
6
7
8
#FASTQ Files in Intermediate Ordner kopieren

for i in ${MERGE[@]}; do
  DIRNAME="${ID}-${i}"

  find .  -name "$DIRNAME"_R1.fastq.gz -exec cp '{}' "$CASE/$UNTERORDNER/Sequenzen/Intermediate_merge_$IDP/R1/$DIRNAME"_R1.fastq.gz \;

  find .  -name "$DIRNAME"_R2.fastq.gz -exec cp '{}' "$CASE/$UNTERORDNER/Sequenzen/Intermediate_merge_$IDP/R2/$DIRNAME"_R2.fastq.gz \;

Alle gewünschten Files werden gefunden und richtig kopiert aber folgendes steht in der Shell:

1
cp: './SC21-2021-99-4/Sequenzen/Intermediate_merge_1/R1/SC2-2021-99-1-2_R1.fastq.gz' und '/NAS/Auswertung/Auftrag/2021/SC2-2021/SC21-2021-99-4/Sequenzen/Intermediate_merge_1/R1/SC2-2021-99-1-2_R1.fastq.gz' sind dieselbe Datei

Wo ist hier der Fehler?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7782

Vermutlich liegt es daran, daß find die bereits von dir kopierten Dateien findet und nochmal kopieren will.

Du machst ja find . und wenn dein Kopierziel irgendein Unterordner ist von . dann läuft find da eben auch noch mit hinein.

Der einfachste Weg das zu umgehen ist das Kopierziel in einem anderen Pfad zu haben der sich nicht mit . überschneidet. Ansonsten musst du den Zielpfad von deiner Suche ausschließen. Eine mögliche Option dafür ist -prune (siehe Beispiel in der Manpage).

Alternativ könntest du auch die Ziel-Dateinamen so ändern, daß find sie ignoriert, und die Dateien in einem zweiten Durchgang wieder umbenennen.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13176

SK-N-BE schrieb:

Alle gewünschten Files werden gefunden und richtig kopiert aber folgendes steht in der Shell:

1
cp: './SC21-2021-99-4/Sequenzen/Intermediate_merge_1/R1/SC2-2021-99-1-2_R1.fastq.gz' und '/NAS/Auswertung/Auftrag/2021/SC2-2021/SC21-2021-99-4/Sequenzen/Intermediate_merge_1/R1/SC2-2021-99-1-2_R1.fastq.gz' sind dieselbe Datei

Wo ist hier der Fehler?

Ich gehe davon aus, dass $PWD /NAS/Auswertung/Auftrag/2021 ist, was bedeutet, dass alle gefundenen Dateien auf sich selbst kopiert würden. Generell wäre ich vorsichtig, solche Skripte mit "." zu schreiben, weil das irgendwo sein kann. Mindestens sollten man verifizieren, dass das aktuelle Verzeichnis legal ist oder nicht mit den Zielverzeichnissen überlappt.

Da ich nur einen klitzekleinen Ausschnitt Deines Skriptes sehe und auch nicht weiß, was Dein übergeordnetes Ziel ist, kann ich nicht viel mehr dazu sagen.

SK-N-BE

(Themenstarter)

Anmeldungsdatum:
14. Juni 2018

Beiträge: 120

Vielen Dank ihr beiden.

Ich gehe davon aus, dass $PWD /NAS/Auswertung/Auftrag/2021 ist, was bedeutet, dass alle gefundenen Dateien auf sich selbst kopiert würden. Generell wäre ich vorsichtig, solche Skripte mit "." zu schreiben, weil das irgendwo sein kann. Mindestens sollten man verifizieren, dass das aktuelle Verzeichnis legal ist oder nicht mit den Zielverzeichnissen überlappt.

Wie könnte ich es denn anders machen? Ich habe mir das alles selber durch learning by doing beigebracht und ehrlich gesagt eigentlich keine Ahnung. Meine Skripte funktionieren aber immer irgendwie irgendwann 😉 Ich kann gerne das gesamte Skript hier rein kopieren. Ist auch nicht so lang.

Wie Frostschutz vorgeschlagen hat, habe ich nun den Zieldatei-Namen so abgeändert, dass er durch find nicht mehr gefunden wird:

1
2
3
4
for i in ${MERGE[@]}; do
  DIRNAME="${ID}-${i}"

  find .  -name "$DIRNAME"_R1.fastq.gz -exec cp '{}' "$CASE/$UNTERORDNER/Sequenzen/Intermediate_merge_$IDP/R1/$DIRNAME"_R1_Kopie.fastq.gz \;

Also einfach ein Kopie hinten dran gehängt. Es ist insofern egal wie die Zieldatei genannt wird, weil der ganze Ordner am Schluss gelöscht wird nachdem alle Dateien im Zielordner zusammengefügt und woanders abgespeichert wurden.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13176

SK-N-BE schrieb:

Wie könnte ich es denn anders machen? Ich habe mir das alles selber durch learning by doing beigebracht und ehrlich gesagt eigentlich keine Ahnung. Meine Skripte funktionieren aber immer irgendwie irgendwann 😉

Das ist ja schon mal gut. 👍

Ich kann gerne das gesamte Skript hier rein kopieren. Ist auch nicht so lang.

Meistens finde ich es hilfreicher, wenn jemand in Prosa erklärt, was er eigentlich tun will. Du kannst natürlich trotzdem das Skript posten. In meiner Erfahrung neigt man dann aber dazu, sich mit den Details der konkreten Lösung zu beschäftigen, anstatt den Ansatz zu untersuchen.

SK-N-BE

(Themenstarter)

Anmeldungsdatum:
14. Juni 2018

Beiträge: 120

Meistens finde ich es hilfreicher, wenn jemand in Prosa erklärt, was er eigentlich tun will. Du kannst natürlich trotzdem das Skript posten. In meiner Erfahrung neigt man dann aber dazu, sich mit den Details der konkreten Lösung zu beschäftigen, anstatt den Ansatz zu untersuchen.

Ich bin Biologin und sequenziere. Also ich entschlüssel DNA Sequenzen. Die Auswertung der Daten erfordert ziemlich viel Rechenleistung und ist zum Teil auch recht komplex. Es gibt viele gute Linux-basierte Softwares, die aber zum Teil extrem lange Befehle benötigen. Daher habe ich einige Skripte verfasst um die Auswertung etwas mehr zu automatisieren. Denn wenn man 50 Proben hat und dann für jede Probe manuell einen dreizeiligen Befehl verfassen muss, dreht man irgendwann durch.

In diesem Skript möchte ich sogenannte FASTQ Files zusammenführen. fastq.gz Files sind die Sequenzier-Rohdaten und zwischen 100-600 MB groß. Manchmal ist die Probe an sich schon recht gering konzentriert und es ist schwer genügend Daten bei der Sequenzierung zu erhalten. Also Sequenzieren wir doppelt oder dreifach und fügen danach die FASTQ Dateien zusammen.

das Skript soll nun folgendes tun:

1. Alle FASTQ Files finden, die zu einer bestimmten Probe gehören:

1
find .  -name $ID-$IDP*fastq.gz -print

Wobei $ID die Projektnummer ist und $IDP die ID der Probe (wird vorher über read -p "ermittelt"

2. Nach Angabe welche FASTQ Files zusammengefügt werden sollen (über read -p), sollen diese zunächst in einen neuen Ordner, den man definiert, kopiert werden und dann zusammengefügt werden. Eigentlich war es das schon 😉

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
read -p "Bitte geben Sie an welche Proben zusammengefügt werden sollen:" MERGE

read -p "Bitte geben Sie an in welchem Projekt-Unterordner die zusammgeführten FASTQ Dateien gespeichert werden sollen:" UNTERORDNER


for i in ${MERGE[@]}; do
  DIRNAME="${ID}-${i}"

  find .  -name "$DIRNAME"_R1.fastq.gz -exec cp '{}' "$CASE/$UNTERORDNER/Sequenzen/Intermediate_merge_$IDP/R1/$DIRNAME"_R1_Kopie.fastq.gz \;

 done

cat "$CASE"/"$UNTERORDNER"/Sequenzen/Intermediate_merge_"$IDP"/R1/*.fastq.gz >> "$CASE"/"$UNTERORDNER"/Sequenzen/FASTQ/"$ID"-"$IDP"/"$ID"-"$IDP"_R1.fastq.gz

Zwischendurch werden noch Ordner generiert (if Schleife ob UNTERORDNER vorhanden ist. Wenn nicht, wird ein neuer generiert) und am Ende wird noch einmal überprüft, ob die neu erstellte fastq.gz Datei auch wirklich vorhanden ist und der komplette Intermediate Ordner gelöscht.

Ich habe das Skript überprüft und es tut genau das, was es tun soll. Wenn du aber noch Ideen hast, wie man das einfacher gestalten kann, dann gerne her damit. Das Suchen der Dateien hat zunächst recht lange gedauert, aber seitdem ich nur noch nach fastq.gz Files suche, ist es OK. Das Suchen mit anschließendem Zusammenfügen dauert eine Weile, aber wenn ich 2x 600MB Proben habe, ist das vermutlich nicht verwunderlich. Mein Rechner hat auch nur 64 GB RAM. Wenn man bedenkt, dass viele in meinem Bereich mit 500 GB RAM arbeiten, ist das schon sehr sehr wenig. Aber bald kommt ein neuer Rechner 😉

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11250

Wohnort: München

Gibt es denn einen zwingenden Grund dafür die Dateien mit den Sequenzen erst mal zu kopieren und dann später wieder zu löschen? Falls man darauf verzichten kann, dürfte das schneller gehen die Pfade einzusammeln (kann man in einem Array speichern) und dann an cat als Argumente zu übergeben (solange die Anzahl der Dateien nicht die Zahl der maximalen Argumente übersteigt, die man cat mitgeben kann):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/bin/bash
read -p "Bitte geben Sie an welche Proben zusammengefügt werden sollen:" MERGE

read -p "Bitte geben Sie an in welchem Projekt-Unterordner die zusammgeführten FASTQ Dateien gespeichert werden sollen:" UNTERORDNER


for i in ${MERGE[@]}; do
  DIRNAME="${ID}-${i}"
  readarray -d $'\0' project_files < <(find . -name "$DIRNAME"_R1.fastq.gz -print0)

 done

echo "Führe die folgenden Dateien zusammen:"
printf "%s\n" "${project_files[@]}"
cat "${project_files[@]}" >> "${CASE}/${UNTERORDNER}/Sequenzen/FASTQ/${ID}-${IDP}/${ID}-${IDP}"_R1.fastq.gz

SK-N-BE schrieb:

Zwischendurch werden noch Ordner generiert (if Schleife ob UNTERORDNER vorhanden ist. Wenn nicht, wird ein neuer generiert)

Da würde ich mir mal den Schalter -p für mkdir genauer ansehen - damit kann man Verzeichnisse inkl. Unterordnern auf einen Rutsch erzeugen und falls sie schon existieren, gibt es keinen Fehler.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13176

SK-N-BE schrieb:

Das ist doch schon mal eine super Beschreibung. 👍

Ich bin Biologin und sequenziere. Also ich entschlüssel DNA Sequenzen. Die Auswertung der Daten erfordert ziemlich viel Rechenleistung und ist zum Teil auch recht komplex. Es gibt viele gute Linux-basierte Softwares, die aber zum Teil extrem lange Befehle benötigen. Daher habe ich einige Skripte verfasst um die Auswertung etwas mehr zu automatisieren. Denn wenn man 50 Proben hat und dann für jede Probe manuell einen dreizeiligen Befehl verfassen muss, dreht man irgendwann durch.

Klar.

In diesem Skript möchte ich sogenannte FASTQ Files zusammenführen.

Was genau heißt "zusammenführen"? Und: soll ein Durchlauf des Skriptes eine Zusammenfügung machen oder mehrere? Anders gefragt: führt jeder Wert in MERGE zu einer separaten Ausgabedatei oder sollen alle gefundenen Dateien in einer einzigen Datei zusammen gefügt werden?

fastq.gz Files sind die Sequenzier-Rohdaten und zwischen 100-600 MB groß. Manchmal ist die Probe an sich schon recht gering konzentriert und es ist schwer genügend Daten bei der Sequenzierung zu erhalten. Also Sequenzieren wir doppelt oder dreifach und fügen danach die FASTQ Dateien zusammen.

Spielt die Reihenfolge beim Zusammenfügen eine Rolle?

das Skript soll nun folgendes tun:

1. Alle FASTQ Files finden, die zu einer bestimmten Probe gehören:

1
find .  -name $ID-$IDP*fastq.gz -print

Wobei $ID die Projektnummer ist und $IDP die ID der Probe (wird vorher über read -p "ermittelt"

Die Information würde ich als Skriptargumente übergeben - dann kann man leichter automatisieren (mehrere Skripte zusammen stöpseln).

2. Nach Angabe welche FASTQ Files zusammengefügt werden sollen (über read -p), sollen diese zunächst in einen neuen Ordner, den man definiert, kopiert werden und dann zusammengefügt werden. Eigentlich war es das schon 😉

Das ist ein überflüssiger Kopiervorgang scheint mir.

SK-N-BE

(Themenstarter)

Anmeldungsdatum:
14. Juni 2018

Beiträge: 120

Moin, danke für eure Antworten! Ich sehe mir eure Vorschläge mal genauer an, wenn ich Zeit dazu finde.

Gibt es denn einen zwingenden Grund dafür die Dateien mit den Sequenzen erst mal zu kopieren und dann später wieder zu löschen?

ja leider gibt es einen zwingenden Grund, weil die Proben nicht unbedingt alle in demselben Auftragsordner sind. Hatte es erst anders probiert. Aber es machte irgendwie alles komplizierter. Einfacher ist es alles in einem Ordner zu kopieren und dann über cat die FASTQ dateien zusammenzuführen:

1
cat "$CASE"/"$UNTERORDNER"/Sequenzen/Intermediate_merge_"$IDP"/R1/*.fastq.gz >> "$CASE"/"$UNTERORDNER"/Sequenzen/FASTQ/"$ID"-"$IDP"/"$ID"-"$IDP"_R1.fastq.gz

Was genau heißt "zusammenführen"? Und: soll ein Durchlauf des Skriptes eine Zusammenfügung machen oder mehrere? Anders gefragt: führt jeder Wert in MERGE zu einer separaten Ausgabedatei oder sollen alle gefundenen Dateien in einer einzigen Datei zusammen gefügt werden?

FASTQ Dateien sind riesige .gz Dateien mit den Sequenzier-Rohdaten. Manchmal haben wir für eine Probe nicht genug Daten um diese auswerten zu können. Daher seuqenzieren wir zweimal oder sogar dreimal dieselbe Probe. Nach der Sequenzierung werden alle diese Daten zusammengefügt - also zwei oder drei .gz Dateien zu einer zusammengefügt.

Insgesamt werden am Ende zwei gz Dateien erstellt. Alle, die im Dateinamen "R1" haben kommen in eine und alle, die "R2" haben in die zweite.

Spielt die Reihenfolge beim Zusammenfügen eine Rolle?

Ne eigentlich nicht...

Die Information würde ich als Skriptargumente übergeben - dann kann man leichter automatisieren (mehrere Skripte zusammen stöpseln).

Was meinst du mit Skriptargumente?

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13176

SK-N-BE schrieb:

Gibt es denn einen zwingenden Grund dafür die Dateien mit den Sequenzen erst mal zu kopieren und dann später wieder zu löschen?

ja leider gibt es einen zwingenden Grund, weil die Proben nicht unbedingt alle in demselben Auftragsordner sind. Hatte es erst anders probiert. Aber es machte irgendwie alles komplizierter. Einfacher ist es alles in einem Ordner zu kopieren und dann über cat die FASTQ dateien zusammenzuführen:

Das ist kein zwingender Grund. Solange man alle Dateien verlässlich ermitteln kann, kann man sie auch am Stück verarbeiten, ohne sie zu kopieren.

FASTQ Dateien sind riesige .gz Dateien mit den Sequenzier-Rohdaten. Manchmal haben wir für eine Probe nicht genug Daten um diese auswerten zu können. Daher seuqenzieren wir zweimal oder sogar dreimal dieselbe Probe. Nach der Sequenzierung werden alle diese Daten zusammengefügt - also zwei oder drei .gz Dateien zu einer zusammengefügt.

Also, ich vermute, Du willst sagen, dass sie aneinander gehängt werden. Da tauchte ja ein cat auf.

Insgesamt werden am Ende zwei gz Dateien erstellt. Alle, die im Dateinamen "R1" haben kommen in eine und alle, die "R2" haben in die zweite.

Ah. Wie sollen denn die beiden Ausgabedateien nach der Kombination aller Inputs für 1 und 2 benannt werden?

Spielt die Reihenfolge beim Zusammenfügen eine Rolle?

Ne eigentlich nicht...

OK

Die Information würde ich als Skriptargumente übergeben - dann kann man leichter automatisieren (mehrere Skripte zusammen stöpseln).

Was meinst du mit Skriptargumente?

Das, was Du nach dem Namen des Programms auf der Kommandozeile angibst.

Antworten |