Lista plików posortowana numerycznie


122

Mam kilka plików od log1do log164.

Próbuję LISTĘ katalog (posortowany) w terminalu UNIX, ale funkcje sortowania zapewniają tylko taki format:

home:logs Home$ ls -1 | sort
log1.gz
log10.gz
log100.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz
...etc

Chcę to

home:logs Home$ ls -1 | sort
log1.gz
log2.gz
log3.gz
log4.gz
log5.gz
log6.gz
log7.gz
...{more here}
log99.gz
log100.gz
log101.gz
log102.gz
...etc

Wszelkie sugestie dotyczące tego, czego mógłbym to zrobić?


8
To jest absolutnie pytanie programistyczne i nie zasługuje na migrację tylko dlatego, że odpowiedź dotyczy mało programowania w języku powłoki !!!
tchrist

Jeśli wiesz z góry, że jesteś one nazwane log1.gzprzez log164.gz, a następnie co ty nawet trzeba ls -1nimi?
ruakh

1
@ruakh ls -1 wyświetla wyniki w jednej kolumnie, a nie w poprzek

3
@Rabiani: Wiem, co ls -1robi: wyświetla nazwy plików. Ponieważ znasz już nazwy plików, nie rozumiem, do czego go potrzebujesz. Ale skoro zaakceptowałeś odpowiedź Kevina, teraz wiem: nie potrzebujesz jej. Co ma sens. :-)
ruakh

Odpowiedzi:


40

bashnawiasy klamrowe {}wyliczą je w kolejności:

for file in log{1..164}.gz; do
    process "$file"
done

266

Dlaczego nie skorzystać z wbudowanej lsfunkcji w tym konkretnym przypadku, a mianowicie

-v natural sort of (version) numbers within text

Na przykład ls -1v log*


Niesamowite rozwiązanie, choć chciałbym, aby było równie proste rozwiązanie sortna wypadek, gdyby ktoś miał tablicę ciągów zamiast katalogu plików
Hubro

23
Na BSD / OSX ta opcja jest coś innego: -v - Force unedited printing of non-graphic characters.
kenorb

Niestety opcja -v nie jest dostępna w systemie AIX (6.1)
bouvierr 17.10.16

6
To powinna być najlepsza odpowiedź.
32r34wgf3e

1
w systemie MacOS to zadziała, nie można znaleźć opcji, jak wspomniano, tylkols | sort -n
Ricky Levi

47

Z GNU ls (tj. W Linuksie, Cygwin lub innych systemach, w których GNU jest specjalnie zainstalowany):

ls -v

W Zsh:

echo *(n)

W innych muszlach:

echo log?.gz log??.gz log???.gz

Zastąp echo, printf '%s\n'jeśli chcesz, aby każda nazwa pliku znajdowała się w osobnej linii.

Jeśli chcesz także metadanych pliku ( ls -l) i nie masz GNU ls, musisz wywoływać lsosobno dla każdej nazwy pliku lub grupy nazw plików, które chcesz zobaczyć w porządku leksykograficznym.

ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz

Aby uniknąć tych trudności, używaj wystarczającej liczby zer wiodących w nazwach plików, aby sortowanie leksykograficzne było przyjazne dla człowieka ( log001.gzitp.).


29

Chociaż rozwiązanie ls -1vjest z pewnością najładniejsze w tym konkretnym przypadku, myślę, że dobrze jest mieć takie, które działa sorttak jak w pierwotnym pytaniu, ponieważ działa to również wtedy, gdy twój wkład nie pochodzi ls. W takim przypadku możesz użyć:

ls -1 | sort -n -k1.4

Ta -nopcja nakazuje sortowaniu sortowanie numeryczne i -k 1.4ustawia klucz sortowania na pierwsze pole (w tym przypadku jest to cała nazwa pliku), zaczynając od czwartego znaku do ostatniego.


W moim przypadku ls -1 | sort -n -k1.4nie działa. Daje nieposortowane początkowo do 4 znaków, a następnie posortowane po 4 znaku. Użyłem ls -1 |sort | sort -n -k1.4zamiast tego i działało idealnie.
Prabhu

3
@Prabhu, zamiast tego możesz zrobić sort -k1.1,1.3 -k1.4n. sortimplementacje nie muszą być stabilne, więc twoje podejście nie będzie działać ze wszystkimi implementacjami. Zobacz także -Vopcję GNU i FreeBSD sort.
Stéphane Chazelas

21

GNU sort(dostępny w Linuksie) ma tryb „sortowania wersji”, który interpretuje liczby w liczbach innych niż liczby tak, jak prosisz:

Od man 1 sort:

    -V, --version-sort
           natural sort of (version) numbers within text

(Tworzenie pustych plików testowych do wyświetlenia
touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz:)

Twój przykładowy przypadek, dodając -Vopcję (lub --version-sort):

ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz


3

Moja wersja Solaris nie obsługuje ls -v(grrr). A rozwiązanie sortowania podane powyżej 1) wymaga znajomości pozycji cyfr w nazwie pliku, a 2) nie obsługuje takich rzeczy, jak wieloczęściowe numery wersji.

Poniższe podejście jest kompatybilne z Solaris, nie wymaga wcześniejszej znajomości pozycji cyfr i obsługuje numery wersji z 2, 3 lub 4 komponentami (jak: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Służy również sort -fdo składania razem wielkich i małych liter i odpowiednio obsługuje katalogi zmiatane z plikami:

ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n

Pamiętaj, że ta wersja ogranicza pierwszy składnik do jednej cyfry.

Jeśli Twój docelowy system operacyjny obsługuje ls -v, jest to zdecydowanie najlepsze rozwiązanie.


1

Rozwiązanie Perla:

ls log*.gz | perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; push @A, $_; END{ print sort { getnum $a <=> $b } @A}'

1
$ ls
log101.gz  log102.gz  log103.gz  log104.gz  log105.gz  log106.gz  log10.gz  log1.gz
$ ls | sort -t . -n -k1.4
log1.gz
log10.gz
log101.gz
log102.gz
log103.gz
log104.gz
log105.gz
log106.gz

1
Tutaj -t .jest zbyteczne.
Stéphane Chazelas

0

To zadziałało dla mnie.

Mam pliki 1.jpg 2.jpg ... 18.jpg

$ echo *.jpg | tr -s ' ' '\n' | sort -n

sortjest mylony z lswydrukiem z powodu niezadrukowanych kolorowych znaków. Jeśli spróbujesz:

ls -1 --color=none *.jpg | sort -n

będzie działać idealnie.

sortmoże zignorować niedrukowalne znaki z -iopcją, ale nadal nie działa i nie wiem dlaczego.

Ale zawsze możesz usunąć taki kolor i sortzadziała:

ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n

Mam nadzieję, że pewnego dnia sortbędzie na to dostępna opcja.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.