Mám spoustu souborů z log1
to log164
.
Snažím se SEZNAM adresář (seřazený) v terminálu UNIX, ale funkce třídění poskytují pouze následující formát:
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
To, co chci, je
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
Nějaké návrhy na to, co bych mohl použít k tomu?
bash
rovnátka, {}
, vyjmenuje je v pořadí:
for file in log{1..164}.gz; do
process "$file"
done
Proč nepoužívat vestavěnou funkci ls
pro tento konkrétní případ:
-v natural sort of (version) numbers within text
Například ls -1v log*
S GNU ls (tj. V systémech Linux, Cygwin nebo jiných systémech, které mají GNU ls)):
ls -v
V zsh:
echo *(n)
V jiných skořápkách:
echo log?.gz log??.gz log???.gz
Nahraďte echo
za printf '%s\n'
Pokud chcete, aby každý název souboru byl na samostatném řádku.
Pokud chcete také metadata souboru (ls -l
) a nemáte GNU ls, budete muset zavolat ls
zvlášť pro každý název souboru nebo skupinu názvů souborů, které chcete vidět v lexikografii objednat.
ls -ld log?.gz; ls -ld log??.gz; ls -ld log???.gz
Chcete-li se těmto potížím vyhnout, použijte v názvech souborů dostatek úvodních nul, aby lexikografické řazení bylo přátelské pro člověka (log001.gz
, atd).
Zatímco řešení ls -1v
je určitě nejhezčí v tomto konkrétním případě, myslím, že je dobré mít také ten, který pracuje s sort
jako v původní otázce, protože to funguje také, když váš vstup nepochází z ls
. V tomto případě můžete použít:
ls -1 | sort -n -k1.4
The -n
volba říká, že se má třídit číselně, a -k 1.4
nastaví klíč řazení na první pole (v tomto případě celý název souboru) počínaje 4. znakem až po poslední.
Režim GNU sort
(jak je k dispozici v systému Linux)) má režim třídění verzí, který interpretuje čísla uvnitř nečísel přesně podle vašich požadavků:
Z man 1 sort
:
-V, --version-sort natural sort of (version) numbers within text
(Vytváření prázdných testovacích souborů do seznamu:touch log1.gz log2.gz log3.gz log99.gz log100.gz log101.gz log102.gz
)
Váš příklad, přidání -V
možnost (nebo --version-sort
):
ls -1 log*.gz | sort -V
log1.gz
log2.gz
log3.gz
log99.gz
log100.gz
log101.gz
log102.gz
pokud používáte Mac nebo BSD, zkuste toto:
ls -1 *.jpg | sort -n
Moje verze systému Solaris nepodporuje ls -v
(grrr). A řešení řazení uvedené výše 1) vyžaduje znalost pozice číslic v názvu souboru a 2) nezpracovává věci jako čísla vícedílných verzí.
Níže uvedený přístup je kompatibilní se systémem Solaris, nevyžaduje předběžné poznání pozic číslic a zpracovává čísla verzí se 2, 3 nebo 4 komponentami (jako: a-1.2, foo-5.6.7, bar_baz_9.10.11.12). Používá také sort -f
složit velká a malá písmena dohromady a správně zpracovat adresáře smíchané se soubory:
ls -d | sort -f -t . -k 1,1 -k 2,2n -k 3,3n -k 4,4n
Tato verze omezuje první součást na jednu číslici.
Pokud vaše cílové operační systémy podporují ls -v
, to je jasně nejlepší řešení.
Perl řešení:
ls log*.gz | Perl -ne 'sub getnum{ $_[0] =~ /log(\d+)\.gz/; $1 }; Push @A, $_; END{ print sort { getnum $a <=> $b } @A}'
$ 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
To pro mě fungovalo.
Mám soubory 1.jpg 2.jpg ... 18.jpg
$ echo *.jpg | tr -s ' ' '\n' | sort -n
sort
je zaměňován s výstupem ls
kvůli netisknutelným barevným znakům. Pokud to zkusíte:
ls -1 --color=none *.jpg | sort -n
bude to fungovat perfektně.
sort
může ignorovat netisknutelné znaky s volbou -i
, ale stále to nefunguje a já nevím proč.
Vždy však můžete pruhovat takovou barvu a sort
bude fungovat:
ls -1 --color=always *.jpg | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g" | sort -n
Doufám, že jednoho dne sort
bude mít na to možnost.