2012-04-24 20 views
22

Chciałbym zdefiniować prosty skrót połączenia do gs (ghostscript) za pomocą skryptu powłoki. Pierwszy argument (argumenty) podaje wszystkie pliki, które powinny zostać scalone, ostatni podaje nazwę pliku wyjściowego. Oczywiście, poniższe elementy nie działają (służy tylko do wskazania celu):Jak zdefiniować skrypt powłoki ze zmienną liczbą argumentów?

#!/bin/sh 
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$last $1 $2 ... 

Jak można to zrobić?

Zazwyczaj można nazwać ten skrypt przez myscript infile1.pdf infile2.pdf ... outfile.pdf lub myscript *.pdf outfile.pdf.

Odpowiedz

34

Zmienne bash [email protected] i $* rozwijają się na listę argumentów linii poleceń. Ogólnie rzecz biorąc, będziesz chciał użyć "[email protected]" (czyli [email protected] w otoczeniu podwójnych cudzysłowów). Będzie to słuszne, jeśli ktoś przekaże skryptowi argument zawierający białe spacje.

Więc jeśli miał to w skrypcie:

outputfile=$1 
shift 
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$outputfile "[email protected]" 

I nazywa skrypt tak:

myscript out.pdf foo.ps bar.ps "another file.ps" 

ten rozwinie się do:

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=out.pdf foo.ps bar.ps "another file.ps" 

Przeczytaj "Special Parameters" sekcja man, aby uzyskać więcej informacji.

+0

Dzięki larsks. Czy możliwe jest podanie nazwy pliku wyjściowego jako * ostatniego * (nie pierwszego) argumentu? –

+0

Marius Hofert: Nie można łatwo przesunąć ostatniego elementu, więc jest to nieco trudniejsze. Coś takiego: 'outputfile = $ {@: -1}; args = ("$ {@: 1: $ (($ {# @} - 1))}") '. Powinieneś przyjąć tę odpowiedź larsków. – jordanm

+0

Ty * możesz *, ale to trochę brzydkie. Idelic ma przykład w swojej odpowiedzi. Kończy się to o wiele więcej w twoim kodzie. – larsks

18

Aby przekazać plik wyjściowy jako ostatni argument, użyj tablicy:

ARGS=("[email protected]") 
# Get the last argument 
outputfile=${ARGS[-1]} 
# Drop it from the array 
unset ARGS[${#ARGS[@]}-1] 

exec gs ... -sOUTPUTFILE=$outputfile "${ARGS[@]}" 

Przed wersji 4, bash nie pozwalają negatywnych indeksów w macierzach (i wyprodukował błąd zgłoszony przez Marius w komentarzach) , więc jeśli używasz 3.x, musisz użyć znacznie brzydszego, niż w przypadku basha 4.x, ponieważ jest on znacznie brzydszy.

+0

Otrzymuję: gsMerge infile1.pdf infile2.pdf all.pdf /usr/bin/gsMerge: wiersz 4: ARGS: niepoprawny indeks tablicy **** Nie można otworzyć początkowego urządzenia, opuszczając. –

+0

@Marius: Prawdopodobnie używasz starej wersji 'bash'. Zaktualizowałem odpowiedź, aby objąć tę sprawę. – Idelic

+0

Dzięki, Idelic, bardzo dobrze. –

7

Aby uzyskać dostęp do ostatniego argumentu, oprócz odpowiedzi Idelic za wyżej, można również zrobić:

echo "${@: $#}" 

Odczytuje wszystkie argumenty i drukuje je począwszy od ostatniego. W ten sposób możesz również uzyskać dostęp do N ostatnich argumentów, na przykład dla ostatnich trzech argumentów:

echo "${@: $#-2}" 

$ ./script "what does" "this script" "do" "?" 
this script do ? 
+0

Wow, to jest niesamowite. Gdzie jest to zdefiniowane w instrukcji? I czy istnieje wersja tego zakresu? –

+0

Zobacz tę odpowiedź: [link] (https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash) o tablicach splicingu, powyższa odpowiedź jest po prostu używana do pokrojenia tablicy argumentów wejściowych. –

Powiązane problemy