Wie sortiere ich Dateien nach einem Teil des Dateinamens?

7

Angesichts der folgenden Dateien:

ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
XYZ38390.SC00.Statue_WKP

Wie kann ich sie alle basierend auf dem SCWert wie folgt auflisten:

XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP
MRKR
quelle

Antworten:

8

In diesem speziellen Fall, in dem Ihre Dateinamen keine Leerzeichen oder andere seltsame Zeichen enthalten, können Sie sie verwenden lsund weiterleiten sort:

$ ls -d -- *.SC* | sort -t. -k2
XYZ38390.SC00.Statue_WKP
ABC38388.SC01.StatueGrade_MKP
ABC38388.SC02.Statue_GKP
DEF38389.SC03.Statue_HKP

Die -tSätze der Feldtrennzeichen und die -k2teilt , sortum auf dem Teil der Linie 2 mit der Ausgangs Sortieren basierend nd Feld (Verwendung -k2,2für den zweiten Bereich nur ).

In komplexeren Fällen können Sie jeden Dateinamen gefolgt vom NULL-Zeichen ( \0) drucken und dann sortmit seiner -zOption an GNU weiterleiten, um ihn anzuweisen, NULL-getrennte Zeilen zu lesen, und schließlich trdas \0Zurück in ändern \n:

printf '%s\0' *SC* | sort -zt. -k2 | tr '\0' '\n'
terdon
quelle
Vielen Dank an alle ... "-k" -Parameter in der Art sind für mich verwirrend ... auf welcher Basis hat es das Feld aufgenommen, verwirrt mich ... wie k2 für das zweite Feld?
MRKR
@MRKR the -t.weist es an, es .als Feldtrennzeichen zu verwenden, sodass es -k2sich auf das zweite Feld bezieht, wie durch definiert ..
Terdon
@MRKR Wenn eine der Antworten hier Ihr Problem gelöst hat, nehmen Sie sich bitte einen Moment Zeit und akzeptieren Sie es, indem Sie auf das Häkchen links klicken. Dadurch wird die Frage als beantwortet markiert und auf den Stack Exchange-Websites wird der Dank ausgesprochen.
Terdon
4

Mit zsh können Sie Ihre eigene Sortierreihenfolge für Globs mit den Qualifikationsmerkmalen oeoder glob definieren o+:

ls -lUd -- *(oe['REPLY=${REPLY#*.SC}'])

oder:

bysc() REPLY=${REPLY#*.SC}
ls -lUd -- *(o+bysc)

Die Sortierfunktion empfängt den Dateinamen in $REPLYund soll eine Zeichenfolge zurückgeben, nach der $REPLYdas Globbing sortiert. Hier geben wir den Teil des Dateinamens rechts vom ersten Auftreten von zurück .SC(oder den vollständigen Dateinamen, wenn er nicht enthalten ist .SC).

Stéphane Chazelas
quelle
1

Verwenden Sie auf einem GNU-System und mit zshoder bashals Shell Folgendes:

find -maxdepth 1 -type f -print0 | sort -z -t. -k3 | \
while IFS="" read -r -d "" f; do
  basename "$f"
done

  • findsucht nach den Dateien im aktuellen Verzeichnis ( -maxdepth 1) und druckt sie null-byte-getrennt ( -print0).
  • sortliest das eingegebene Nullbyte delimited ( -z) und sortiert nach dem Teil des Datensatzes, der im 3. Feld ( -k3) beginnt, das durch einen Punkt ( -t.) getrennt ist.
  • while liest die Eingabe
    • und basenamedruckt seinen Namen ohne Pfad
Chaos
quelle
0

Ich würde - wie ich es oft tue - vorschlagen perl.

perlhat eine Sortierfunktion, mit der Sie eine Vergleichsfunktion angeben können. Diese Vergleichsfunktion ist jeder Test, der zwei Werte annimmt, und kehrt -1, 0oder 1je nach Relativposition.

Es wiederholt die Liste, wobei jeder Wert als $aund festgelegt wird $bund der Test für jedes Element durchgeführt wird.

Also standardmäßig:

$a cmp $b 

zum stringweisen Vergleich oder sort { $a <=> $b }zum numerischen Vergleich .

Infolgedessen können Sie jedoch beliebig komplexe benutzerdefinierte Sortierkriterien anwenden:

#!/usr/bin/perl
use strict;
use warnings;

sub sort_by_sc {
   my ( $a_sc ) = $a =~ m/SC(\d+)/;
   my ( $b_sc ) = $b =~ m/SC(\d+)/;
   return $a_sc <=> $b_sc;
}


my @file_list = qw ( 
    ABC38388.SC01.StatueGrade_MKP
    ABC38388.SC02.Statue_GKP
    DEF38389.SC03.Statue_HKP
    XYZ38390.SC00.Statue_WKP
);

print sort sort_by_sc @file_list;

Oder auf einen Einzeiler, eine Lesung STDINoder eine Datei reduziert (Zeilenvorschub getrennt, was normalerweise gut genug ist):

perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} <>'

Sie können es stattdessen mit dem Ergebnis globeines Verzeichnismusters füttern :

perl -e 'print sort {@x = map {/SC(\d+)/}($a,$b); $x[0] <=> $x[1]} glob ( "*SC*")'
Sobrique
quelle