Mam tę listę plików pdf w katalogu:
c0.pdf c12.pdf c15.pdf c18.pdf c20.pdf c4.pdf c7.pdf
c10.pdf c13.pdf c16.pdf c19.pdf c2.pdf c5.pdf c8.pdf
c11.pdf c14.pdf c17.pdf c1.pdf c3.pdf c6.pdf c9.pdf
Chcę połączyć je za pomocą ghostscript w kolejności numerycznej (podobnej do tej):
gs -q -sPAPERSIZE=a4 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf *.pdf
Ale kolejność rozszerzania powłoki nie odtwarza naturalnego porządku liczb, ale kolejność alfabetyczną:
$ for f in *.pdf; do echo $f; done
c0.pdf
c10.pdf
c11.pdf
c12.pdf
c13.pdf
c14.pdf
c15.pdf
c16.pdf
c17.pdf
c18.pdf
c19.pdf
c1.pdf
c20.pdf
c2.pdf
c3.pdf
c4.pdf
c5.pdf
c6.pdf
c7.pdf
c8.pdf
c9.pdf
Jak mogę osiągnąć pożądaną kolejność w rozwinięciu (jeśli to możliwe bez ręcznego dodawania 0
-paddingu do liczb w nazwach plików)?
Znalazłem sugestie do użycia ls | sort -V
, ale nie mogłem zmusić go do działania w moim konkretnym przypadku użycia.
Odpowiedzi:
W zależności od środowiska możesz używać
ls -v
z GNU coreutils, np .:Lub jeśli korzystasz z najnowszych wersji FreeBSD lub OpenBSD:
źródło
ls -v
będzienatural sort of (version) numbers within text
tak, że mogą być stosowane również ...-V
Funkcjasort
POSIX również nie jest określona. Wydaje się jednak, że rozprzestrzenił się dalej, na przykładsort
obsługuje go zarówno FreeBSD, jak i OpenBSD .ls
używane, sprawdziłem, czy ma opcję samą w sobie zamiastRaz jeszcze na ratunek przybywają kwalifikatory globalne zsh .
źródło
Jeśli wszystkie pliki mają ten sam prefiks (tj. Tekst przed liczbą;
c
w tym przypadku), możesz użyćc?.pdf
rozszerza się doc0.pdf
c1.pdf
...c9.pdf
.c??.pdf
rozwija się doc10.pdf
c11.pdf
…c20.pdf
(i doc99.pdf
, zależnie od przypadku). Chociaż każde słowo wiersza polecenia zawierające znak (i) rozwijające nazwę ścieżki jest rozwijane do listy nazw plików posortowanych (zestawionych) zgodnie zeLC_COLLATE
zmienną, listy wynikające z rozwinięcia sąsiednich symboli wieloznacznych (globów) nie są scalane; są po prostu połączone. (Wydaje mi się, że pamiętam, że strona podręcznika powłoki kiedyś to wyraźnie powiedziała, ale nie mogę jej teraz znaleźć).Oczywiście, jeśli pliki mogą wzrosnąć
c999.pdf
, powinieneś użyćc?.pdf c??.pdf c???.pdf
. Trzeba przyznać, że przy dużej liczbie cyfr może to być nudne. Możesz to trochę skrócić; na przykład, dla (do) pięciu cyfr, możesz użyćc?{,?{,?{,?{,?}}}}.pdf
. Jeśli twoja lista nazw plików jest rzadka (np. Istnieje ac0.pdf
i ac12345.pdf
, ale niekoniecznie każda liczba pomiędzy), prawdopodobnie powinieneś ustawić tęnullglob
opcję. W przeciwnym razie, jeśli (na przykład) nie masz plików z dwucyfrowymi liczbami, otrzymasz dosłownyc??.pdf
argument do swojego programu.Jeśli masz wiele prefiksów (na przykład , i , o numerach od jednego lub dwóch cyfr), można użyć oczywiste brute force podejście:
a<number>.pdf
b<number>.pdf
c<number>.pdf
lub zwinąć do
{a,b,c}?{,?}.pdf
.źródło
ls
,stat
lub cokolwiek innego; a także działa w bash zgodnie z żądaniem.Jeśli nie ma żadnych luk , poniższe informacje mogą okazać się pomocne (choć szkicowe i mało solidne w odniesieniu do przypadków skrajnych i ogólności) - tylko w celu uzyskania pomysłu:
Jeśli mogą występować luki,
[ -f c${i}.pdf ]
można dodać trochę czeków.Edytuj również zobaczyć tę odpowiedź , zgodnie z którą możesz (używając Bash) użyć
źródło
"$FILES"
I"$i"
), chyba że masz dobry powód, aby tego nie robić i jesteś pewien, że wiesz, co robisz. (Podczas gdy nawiasy klamrowe mogą być ważne, nie są tak ważne jak cudzysłowy, więc na przykład"c$i.pdf"
są wystarczająco dobre.) Komenda typu , gdzie zawiera listę plików oddzieloną spacjami, może wydawać się dobrym powodem do użyj bez cytowania (ponieważ nie będzie działać w tym kontekście). … (Ciąg dalszy)gs [
…args…
] $FILES
$FILES
$FILES
"$FILES"
FILES=("c0.pdf")
iFILES+=("c$i.pdf")
); także ta odpowiedź , która wykorzystuje technikę, którą sugeruję.Cytuję i naprawiam odpowiedź Thora ... NIGDY nie analizuj!
Możesz użyć
sort -V
(rozszerzenie inne niż POSIX do sortowania):(dla niektórych poleceń, najwyraźniej dla gs jest takim poleceniem, potrzebujesz „./ ” zamiast „ ” ... jeśli jedno nie działa, spróbuj drugiego)
źródło
stat
ale dodajesz kilka innych problemów (takich jak problemy z uruchamianiem nazw plików z-
, problem, jeśli istnieje zbyt wiele plików,stat
będąc non-przenośny komenda). A ponieważ używałeś operatora split + glob bez dostosowywania IFS lub wyłączania globów, nadal będziesz mieć problemy z nazwami plików ze spacją, tabulatorami lub znakami wieloznacznymi.sort -V
niezawodnie, że trzeba${(z)"$(printf '%s\0' * | sort -zV)"}
wzsh
(chociażzsh
ma(n)
do sortowania już numerycznej) lubreadarray -td '' files < <(printf '%s\0' * | sort -zV)
wbash4.4+
.ls
samego (czyli bez -l), jakie są te inne obawy ? Zauważ, że--
to nie pomogłoby dla pliku o nazwie-
.touch \"test\"; ls -1
na przykład pokazuje'"test"'
na moim ls. Po prostu nie jest przeznaczony do analizowania ... to interfejs użytkownika, a nie polecenie skryptowe.