it-swarm.com.de

BASH: So werden alle Dateien in sortierter Reihenfolge wiederholt

Ich schleife alle Dateien im Verzeichnis mit folgendem Befehl:

for i in *.fas; do some_code; done;

Ich bekomme aber so Ordnung:

vvchr1.fas
vvchr10.fas
vvchr11.fas

anstelle von vvchr1.fas, vvchr2.fas, vvchr3.fas ist die numerische Reihenfolge.

Ich habe Sortierbefehl versucht, aber ohne Erfolg.

41
Perlnika
for i in `ls *.fas | sort -V`; do some_code; done;

wo sort -V nach man sort eine Versionssortierung durchführt - eine natürliche Art von (Versions-) Zahlen im Text

Dasselbe, wenn nur ls verwendet wird:

for i in `ls -v *.fas`; do echo $i; done;
75

Sie erhalten die Dateien in der Reihenfolge ASCII. Dies bedeutet, dass vvchr10* vor vvchr2* steht. Ich weiß, dass Sie Ihre Dateien nicht umbenennen können (mein bioinformatisches Gehirn sagt mir, dass sie Chromosomendaten enthalten, und wir nennen Chromosom 1 einfach nicht "chr01"). Hier ist eine andere Lösung (sort -V, die ich auf keiner finden kann) Betriebssystem, das ich verwende):

ls *.fas | sed 's/^\([^0-9]*\)\([0-9]*\)/\1 \2/' | sort -k2,2n | tr -d ' ' |
while read filename; do
  # do work with $filename
done

Dies ist ein wenig kompliziert und funktioniert nicht mit Dateinamen, die Leerzeichen enthalten.

Eine andere Lösung: Nehmen wir an, wir möchten die Dateien stattdessen in der Reihenfolge ihrer Größe durchlaufen, was für einige Bioinformatik-Aufgaben besser geeignet ist:

du *.fas | sort -k2,2n |
while read filesize filename; do
  # do work with $filename
done

Um die Sortierung umzukehren, fügen Sie einfach r nach -k2,2n hinzu (um -k2,2nr zu erhalten).

4
Kusalananda

Mit der Option sort -g wird der allgemeine numerische Wert verglichen

 for FILE in `ls ./raw/ | sort -g`; do echo "$FILE"; done

0.log 1.log 2.log ... 10.log 11.log

Dies funktioniert nur, wenn der Name der Dateien numerisch ist. Wenn sie eine Zeichenfolge sind, werden sie in alphabetischer Reihenfolge angezeigt. Z.B.:

 for FILE in `ls ./raw/* | sort -g`; do echo "$FILE"; done

raw/0.log raw/10.log raw/11.log ... raw/2.log

3
gtangil
while IFS= read -r  file ; do
    ls -l "$file" # or whatever
done < <(find . -name '*.fas' 2>/dev/null | sed -r -e 's/([0-9]+)/ \1/' | sort -k 2 -n | sed -e 's/ //;'

Behebt das Problem, unter der Annahme, dass die Dateinamen konsistent bleiben, nicht auf sehr aktuelle Versionen von GNU sort angewiesen ist, nicht auf das Lesen der Ausgabe von ls angewiesen ist und nicht der Pipeline zum Opfer fällt Probleme.

1
Sorpigal

Sie meinen, dass Dateien mit der Nummer 10 vor Dateien mit der Nummer 3 in Ihrer Liste stehen? Das ist, weil ls sein Ergebnis sehr einfach sortiert, so dass something-10.whatever kleiner als something-3.whatever ist.

Eine Lösung besteht darin, alle Dateien so umzubenennen, dass sie die gleiche Anzahl von Ziffern haben (die Dateien mit einstelligen Ziffern beginnen mit 0 in der Anzahl).

Wie @ Kusalanandas Lösung (vielleicht einfacher zu merken?), Aber für alle Dateien (?):

array=("$(ls |sed 's/[^0-9]*\([0-9]*\)\..*/\1 &/'| sort -n | sed 's/^[^ ]* //')")
for x in "${array[@]}";do echo "$x";done

Im Wesentlichen einen Sortierschlüssel hinzufügen, sortieren, Sortierschlüssel entfernen.

BEARBEITEN: Kommentar in die entsprechende Lösung verschoben

0
potong

verwenden Sie sort -rh und die while-Schleife

du -sh * | sort -rh | grep -P "avi$" |awk '{print $2}' | while read f; do fp=`pwd`/$f; echo $fp; done;
0
David Okwii