Verschieben Sie Dateien, deren Wert in einer beliebigen Zeile einer bestimmten Spalte über einem Schwellenwert liegt.

Verschieben Sie Dateien, deren Wert in einer beliebigen Zeile einer bestimmten Spalte über einem Schwellenwert liegt.

Ich habe eine große Anzahl von Dateien in einem bestimmten Ordner. Ich möchte diese Dateien NUR WENN sie in einer Zeile der Spalte 4 mindestens 1 Wert über 0,5 haben, in einen Unterordner verschieben. In einem separaten Befehl möchte ich dasselbe tun, aber mit Dateien, die mindestens 2 Zeilen mit Werten über 0,5 in Spalte 4 haben.

Dies ist das allgemeine Format der Dateien (mit Header):

col1  col2  col3  col4  col5  col6
ABC   DEF   5.10  0.94  GHI   JKL
MNO   PQR   8.31  0.37  STU   VWX
ABC   DEF   6.49  0.84  GHI   JKL
MNO   PQR   3.32  0.21  STU   VWX

Einige der Zahlen in Spalte 4 sind in wissenschaftlicher Notation: 8.934553871039306e-05

Mit dem folgenden Code habe ich bisher versucht, Dateien mit mindestens einem Wert über 0,5 in Spalte 4 zu verschieben. Dabei werden alle Dateien in den Unterordner verschoben, auch diejenigen, die die Bedingung nicht erfüllen.

#!/bin/bash

find . -type f -exec awk '$4 >= 0.5' {} \; -exec mv -n {} ./NewFolder/ \;

Antwort1

Damit Ihr Befehl funktioniert, müssen Sie awkmit dem Code 0 beenden, wenn eine Übereinstimmung gefunden wird, oder mit einem Exit-Code ungleich Null, wenn keine Übereinstimmung gefunden wird.

Darüber hinaus sollten Sie die erste Zeile überspringen, da ein nicht numerischer Wert als Zeichenfolge verglichen wird, was zu einer unerwarteten Übereinstimmung führen kann.

find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found=1; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;

Hinweis: Wenn das awkSkript mit mehr als einer Datei aufgerufen wird, bedeutet der Exit-Code, dass in einer der Dateien eine Übereinstimmung gefunden wurde. Der findBefehl stellt sicher, dass immer nur eine Datei gleichzeitig an übergeben wird awk, daher ist dies hier kein Problem.

2. Bearbeitung:

Um Dateien auszuwählen, die mindestens zwei übereinstimmende Zeilen haben, können Sie die Übereinstimmungen zählen.

find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found++; if(found >= 2) exit} END {exit found >= 2}' {} \; -exec mv -n {} ./NewFolder/ \;

Bearbeiten:

Um das Problem zu beheben, dass das Skript Dateien verschiebt, die keinen übereinstimmenden Wert in Spalte 4 haben, können Sie dem awkSkript Code hinzufügen, um Informationen über die übereinstimmende Zeile auszudrucken. Der folgende Code druckt den Dateinamen, die Zeilennummer und die übereinstimmende Zeile, wenn eine Übereinstimmung gefunden wurde.

find . -type f -exec awk 'FNR==1 {next} $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;

Sie erhalten etwas wie

threshold.txt:2:ABC   DEF   5.10  0.94  GHI   JKL

Ich schlage vor, dies zuerst zu tun, um die Ursache des Problems zu finden.

Wenn es Zeilen gibt, die in Spalte 4 einen nicht numerischen Text haben, werden die Werte als Text verglichen. Dies würde beispielsweise dazu führen, dass "abc"größer ist als "0.5".

Eine weitere mögliche Ursache könnte eine Zeile sein, die in Spalte 1 oder 2 Leerzeichen enthält, was zu einer falschen Zuordnung des Textes zu den Spalten führt.

Falls Spalte 4 nicht numerische Werte enthält und Sie diese Zeilen ignorieren möchten, können Sie eine numerische Interpretation erzwingen, indem Sie den Wert wie 0in hinzufügen 0 + $4.

find . -type f -exec awk 'FNR==1 {next} 0 + $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;

Wenn das Problem darin liegt, dass Ihre Felder durch Tabulatoren getrennt sind und die Werte Leerzeichen enthalten können, können Sie den Feldtrenner ( -F "\t") angeben. Das folgende Skript kombiniert dies mit den anderen Änderungen.

find . -type f -exec awk -F "\t" 'FNR==1 {next} 0 + $4 >= 0.5 {found=1; printf "%s:%d:%s\n", FILENAME, FNR, $0; exit} END {exit !found}' {} \; -exec mv -n {} ./NewFolder/ \;

Antwort2

Das awkfunktioniert nicht wirklich. Es werden alle Dateien gefunden, da die Zeichenfolge col4Folgendes erfüllt >=0.5:

$ echo col4 | awk '$1>=0.5'
col4

Sie müssen also den Header überspringen. Sie müssen awk außerdem anweisen, erfolgreich zu beenden, wenn die Datei Ihren Kriterien entspricht, und mit einem Fehler, wenn dies nicht der Fall ist. Etwa so:

find . -type f \
    -exec awk -va=1 '{ if($4 >= 0.5 && NR>1){a=0}} END{exit a}' {} \; \
    -exec mv -n {} ./NewFolder/ \;

Antwort3

Mit einer For-Schleife können Sie Folgendes versuchen:

for i in *; do # *.extension
  [[ -f "$i" && $(awk 'NR>1 && $4 >= 0.5' "$i") ]] && mv "$i" NewFolder/
done

Und für zwei Werte:

for i in *; do  # *.extension
  [[ -f "$i" ]] && [[ $(awk 'NR>1 && $4 >= 0.5' "$i" | wc -l) -ge 2 ]] 
  mv "$i" NewFolder
done

verwandte Informationen