it-swarm.com.de

Einen Bash-Alias ​​erstellen, der einen Parameter annimmt?

Früher habe ich CShell ( csh ) verwendet, mit dem Sie einen Alias ​​erstellen können, der einen Parameter annimmt. Die Notation war ungefähr so

alias junk="mv \\!* ~/.Trash"

In Bash scheint dies nicht zu funktionieren. Da Bash eine Vielzahl nützlicher Funktionen hat, würde ich annehmen, dass diese implementiert wurde, aber ich frage mich, wie.

1107
Hello

Der Bash-Alias ​​akzeptiert keine Parameter direkt. Sie müssen eine Funktion erstellen.

alias akzeptiert keine Parameter, aber eine Funktion kann wie ein Alias ​​aufgerufen werden. Zum Beispiel:

myfunction() {
    #do things with parameters like $1 such as
    mv "$1" "$1.bak"
    cp "$2" "$1"
}


myfunction old.conf new.conf #calls `myfunction`

Übrigens sind die in Ihrem .bashrc und in anderen Dateien definierten Bash-Funktionen als Befehle in Ihrer Shell verfügbar. So können Sie zum Beispiel die frühere Funktion wie folgt aufrufen

$ myfunction original.conf my.conf
1865
arunkumar

Wenn Sie die obige Antwort verfeinern, können Sie wie bei Aliasen eine einzeilige Syntax erhalten, was für Ad-hoc-Definitionen in einer Shell- oder .bashrc-Datei praktischer ist:

bash$ myfunction() { mv "$1" "$1.bak" && cp -i "$2" "$1"; }

bash$ myfunction original.conf my.conf

Vergessen Sie nicht das Semikolon vor der schließenden rechten Klammer. Ebenso für die eigentliche Frage:

csh% alias junk="mv \\!* ~/.Trash"

bash$ junk() { mv "[email protected]" ~/.Trash/; }

Oder:

bash$ junk() { for item in "[email protected]" ; do echo "Trashing: $item" ; mv "$item" ~/.Trash/; done; }
181
Mike Gleason

Die Frage wird einfach falsch gestellt. Sie erstellen keinen Alias, der Parameter akzeptiert, da alias nur einen zweiten Namen für etwas hinzufügt, das bereits vorhanden ist. Die Funktionalität, die das OP benötigt, ist der Befehl function, um eine neue Funktion zu erstellen. Sie müssen die Funktion nicht aliasen, da die Funktion bereits einen Namen hat.

Ich denke du willst so etwas:

function trash() { mv "[email protected]" ~/.Trash; }

Das ist es! Sie können die Parameter $ 1, $ 2, $ 3 usw. verwenden oder sie alle mit $ @ füllen.

103
Evan Langlois

TL; DR: Mach das stattdessen

Es ist viel einfacher und lesbarer, eine Funktion als einen Alias ​​zu verwenden, um Argumente in die Mitte eines Befehls zu setzen.

$ wrap_args() { echo "before [email protected] after"; }
$ wrap_args 1 2 3
before 1 2 3 after

Wenn Sie weiterlesen, lernen Sie Dinge, die Sie über die Verarbeitung von Shell-Argumenten nicht wissen müssen. Wissen ist gefährlich. Erhalten Sie einfach das gewünschte Ergebnis, bevor die dunkle Seite Ihr Schicksal für immer kontrolliert.

Klärung

bash Aliase akzeptieren Argumente, jedoch nur am Ende :

$ alias speak=echo
$ speak hello world
hello world

Das Einfügen von Argumenten in die Mitte eines Befehls über alias ist zwar möglich, wird aber hässlich.

Versuchen Sie das nicht zu Hause, Kinder!

Wenn Sie gerne Einschränkungen umgehen und das tun möchten, was andere für unmöglich halten, finden Sie hier das Rezept. Beschuldigen Sie mich einfach nicht, wenn Ihre Haare zerzaust sind und Ihr Gesicht mit Ruß bedeckt ist, der wie ein verrückter Wissenschaftler wirkt.

Die Problemumgehung besteht darin, die Argumente, die alias nur am Ende akzeptiert, an einen Wrapper zu übergeben, der sie in die Mitte einfügt und dann Ihren Befehl ausführt.

Lösung 1

Wenn Sie wirklich gegen die Verwendung einer Funktion per se sind, können Sie Folgendes verwenden:

$ alias wrap_args='f(){ echo before "[email protected]" after;  unset -f f; }; f'
$ wrap_args x y z
before x y z after

Sie können [email protected] durch $1 ersetzen, wenn Sie nur das erste Argument wünschen.

Erklärung 1

Dadurch wird eine temporäre Funktion f erstellt, der die Argumente übergeben werden (beachten Sie, dass f ganz am Ende aufgerufen wird). Der unset -f entfernt die Funktionsdefinition, wenn der Alias ​​ausgeführt wird, damit er danach nicht herumhängt.

Lösung 2

Sie können auch eine Unterschale verwenden:

$ alias wrap_args='sh -c '\''echo before "[email protected]" after'\'' _'

Erklärung 2

Der Alias ​​erstellt einen Befehl wie:

sh -c 'echo before "[email protected]" after' _

Bemerkungen:

  • Der Platzhalter _ ist erforderlich, kann aber auch beliebig sein. Es wird auf $0 von sh gesetzt und ist erforderlich, damit das erste der vom Benutzer angegebenen Argumente nicht verbraucht wird. Demonstration:

    sh -c 'echo Consumed: "$0" Printing: "[email protected]"' alcohol drunken babble
    Consumed: alcohol Printing: drunken babble
    
  • Die einfachen Anführungszeichen in einfachen Anführungszeichen sind erforderlich. Hier ist ein Beispiel, das nicht mit doppelten Anführungszeichen funktioniert:

    $ sh -c "echo Consumed: $0 Printing: [email protected]" alcohol drunken babble
    Consumed: -bash Printing:
    

    Hier werden die Werte von $0 und [email protected] der interaktiven Shell in Anführungszeichen ersetzt, bevor an sh übergeben wird. Hier ist der Beweis:

    echo "Consumed: $0 Printing: [email protected]"
    Consumed: -bash Printing:
    

    Die einfachen Anführungszeichen stellen sicher, dass diese Variablen nicht von der interaktiven Shell interpretiert und wörtlich an sh -c übergeben werden.

    Sie könnten doppelte Anführungszeichen und \[email protected] verwenden, aber am besten zitieren Sie Ihre Argumente (da sie Leerzeichen enthalten können), und \"\[email protected]\" sieht noch hässlicher aus, kann Ihnen aber dabei helfen, einen Verschleierungswettbewerb zu gewinnen, bei dem die Haare zerzaust sind ist eine Voraussetzung für die Einreise.

94
Tom Hale

Eine alternative Lösung ist die Verwendung von marker , einem kürzlich von mir erstellten Tool, mit dem Sie Befehlsvorlagen mit einem Lesezeichen versehen und den Cursor einfach auf Befehlsplatzhalter setzen können:

commandline marker

Ich habe festgestellt, dass ich die meiste Zeit Shell-Funktionen benutze, damit ich nicht immer wieder häufig verwendete Befehle in die Befehlszeile schreiben muss. Das Problem bei der Verwendung von Funktionen für diesen Anwendungsfall besteht darin, meinem Befehlsvokabular neue Begriffe hinzuzufügen und sich zu merken, auf welche Funktionsparameter sich der Real-Befehl bezieht. Marker Ziel ist es, diese mentale Belastung zu beseitigen.

35

Hier sind drei Beispiele für Funktionen in meinem ~/.bashrc, die im Wesentlichen Aliase sind, die einen Parameter akzeptieren:

#Utility required by all below functions.
#https://stackoverflow.com/questions/369758/how-to-trim-whitespace-from-bash-variable#comment21953456_3232433
alias trim="sed -e 's/^[[:space:]]*//g' -e 's/[[:space:]]*\$//g'"

.

:<<COMMENT
    Alias function for recursive deletion, with are-you-sure Prompt.

    Example:
        srf /home/myusername/Django_files/rest_tutorial/rest_venv/

    Parameter is required, and must be at least one non-whitespace character.

    Short description: Stored in SRF_DESC

    With the following setting, this is *not* added to the history:
        export HISTIGNORE="*rm -r*:srf *"
    - https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash

    See:
    - y/n Prompt: https://stackoverflow.com/a/3232082/2736496
    - Alias w/param: https://stackoverflow.com/a/7131683/2736496
COMMENT
#SRF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
SRF_DESC="srf [path]: Recursive deletion, with y/n Prompt\n"
srf()  {
    #Exit if no parameter is provided (if it's the empty string)
        param=$(echo "$1" | trim)
        echo "$param"
        if [ -z "$param" ]  #http://tldp.org/LDP/abs/html/comparison-ops.html
        then
          echo "Required parameter missing. Cancelled"; return
        fi

    #Actual line-breaks required in order to expand the variable.
    #- https://stackoverflow.com/a/4296147/2736496
    read -r -p "About to
    Sudo rm -rf \"$param\"
Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        Sudo rm -rf "$param"
    else
        echo "Cancelled."
    fi
}

.

:<<COMMENT
    Delete item from history based on its line number. No Prompt.

    Short description: Stored in HX_DESC

    Examples
        hx 112
        hx 3

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HX_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HX_DESC="hx [linenum]: Delete history item at line number\n"
hx()  {
    history -d "$1"
}

.

:<<COMMENT
    Deletes all lines from the history that match a search string, with a
    Prompt. The history file is then reloaded into memory.

    Short description: Stored in HXF_DESC

    Examples
        hxf "rm -rf"
        hxf ^source

    Parameter is required, and must be at least one non-whitespace character.

    With the following setting, this is *not* added to the history:
        export HISTIGNORE="*hxf *"
    - https://superuser.com/questions/232885/can-you-share-wisdom-on-using-histignore-in-bash

    See:
    - https://unix.stackexchange.com/questions/57924/how-to-delete-commands-in-history-matching-a-given-string
COMMENT
#HXF_DESC: For "aliaf" command (with an 'f'). Must end with a newline.
HXF_DESC="hxf [searchterm]: Delete all history items matching search term, with y/n Prompt\n"
hxf()  {
    #Exit if no parameter is provided (if it's the empty string)
        param=$(echo "$1" | trim)
        echo "$param"
        if [ -z "$param" ]  #http://tldp.org/LDP/abs/html/comparison-ops.html
        then
          echo "Required parameter missing. Cancelled"; return
        fi

    read -r -p "About to delete all items from history that match \"$param\". Are you sure? [y/N] " response
    response=${response,,}    # tolower
    if [[ $response =~ ^(yes|y)$ ]]
    then
        #Delete all matched items from the file, and duplicate it to a temp
        #location.
        grep -v "$param" "$HISTFILE" > /tmp/history

        #Clear all items in the current sessions history (in memory). This
        #empties out $HISTFILE.
        history -c

        #Overwrite the actual history file with the temp one.
        mv /tmp/history "$HISTFILE"

        #Now reload it.
        history -r "$HISTFILE"     #Alternative: exec bash
    else
        echo "Cancelled."
    fi
}

Verweise:

10
aliteralmind

Sie müssen lediglich eine Funktion in einem Alias ​​erstellen:

$ alias mkcd='function _mkcd(){mkdir "$1"; cd "$1"}; _mkcd'

Sie müssen doppelte Anführungszeichen um "$ 1" setzen, da einfache Anführungszeichen nicht funktionieren.

6
Ken Tran

Wenn Sie nach einer generischen Methode suchen, um alle Parameter auf eine Funktion anzuwenden, nicht nur auf eine oder zwei oder eine andere fest codierte Menge, können Sie dies folgendermaßen tun:

#!/usr/bin/env bash

# you would want to `source` this file, maybe in your .bash_profile?
function runjar_fn(){
    Java -jar myjar.jar "[email protected]";
}

alias runjar=runjar_fn;

Im obigen Beispiel übergebe ich alle Parameter ab dem Start von runjar an den Alias.

Wenn ich zum Beispiel runjar hi there gemacht hätte, würde es letztendlich Java -jar myjar.jar hi there ausführen. Wenn ich runjar one two three machen würde, würde es Java -jar myjar.jar one two three ausführen.

Ich mag diese [email protected] - basierte Lösung, weil sie mit einer beliebigen Anzahl von Parametern funktioniert.

5
Micah

NB: Falls die Idee nicht offensichtlich ist, ist es eine schlechte Idee, Aliase für etwas anderes als Aliase zu verwenden, wobei der erste die "Funktion in einem Alias" und der zweite die "schwer lesbare Weiterleitung/Quelle" ist. Auch gibt es Mängel (die ich dachte wäre offensichtlich, aber nur für den Fall, dass Sie verwirrt sind: Ich meine nicht, dass sie tatsächlich verwendet werden ... überall!)

.................................................. .................................................. ............................................

Ich habe das schon einmal beantwortet und es war in der Vergangenheit immer so:

alias foo='__foo() { unset -f $0; echo "arg1 for foo=$1"; }; __foo()'

das ist in Ordnung und gut, es sei denn, Sie vermeiden die Verwendung von Funktionen insgesamt. In diesem Fall können Sie die enorme Fähigkeit von bash nutzen, Text umzuleiten:

alias bar='cat <<< '\''echo arg1 for bar=$1'\'' | source /dev/stdin'

Sie sind beide ungefähr gleich lang und geben oder nehmen ein paar Zeichen.

Der real Kicker ist der Zeitunterschied, wobei oben die 'Funktionsmethode' und unten die 'Redirect-Source'-Methode ist. Um diese Theorie zu beweisen, spricht das Timing für sich:

arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.004s sys 0m0.008s  # <--time spent in foo
 real 0m0.000s user 0m0.000s sys 0m0.000s  # <--time spent in bar
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.011s user 0m0.000s sys 0m0.012s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.012s user 0m0.004s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE
[email protected] /usr/bin# time foo FOOVALUE; time bar BARVALUE
arg1 for foo=FOOVALUE
 real 0m0.010s user 0m0.008s sys 0m0.004s
 real 0m0.000s user 0m0.000s sys 0m0.000s
arg1 for bar=BARVALUE

Dies ist der untere Teil von ungefähr 200 Ergebnissen, die in zufälligen Intervallen durchgeführt werden. Es scheint, dass die Erstellung/Zerstörung von Funktionen mehr Zeit benötigt als die Umleitung. Hoffentlich hilft dies zukünftigen Besuchern dieser Frage (wollte sie nicht für mich behalten).

5
osirisgothra

Es gibt berechtigte technische Gründe, eine verallgemeinerte Lösung für das Problem des Bash-Alias ​​zu wollen, der keinen Mechanismus besitzt, um beliebige Argumente neu zu positionieren. Ein Grund ist, dass der Befehl, den Sie ausführen möchten, durch die Änderungen an der Umgebung, die sich aus der Ausführung einer Funktion ergeben, nachteilig beeinflusst wird. In allen anderen Fällen sollten Funktionen verwendet werden.

Was mich kürzlich dazu gezwungen hat, eine Lösung zu finden, ist, dass ich einige abgekürzte Befehle zum Drucken der Definitionen von Variablen und Funktionen erstellen wollte. Deshalb habe ich einige Funktionen für diesen Zweck geschrieben. Es gibt jedoch bestimmte Variablen, die durch einen Funktionsaufruf selbst geändert werden (oder werden können). Darunter sind:

FUNCNAME BASH_SOURCE BASH_LINENO BASH_ARGC BASH_ARGV

Der grundlegende Befehl, den ich (in einer Funktion) verwendet hatte, um variable Defns zu drucken. In der vom Befehl set ausgegebenen Form lautete:

sv () { set | grep --color=never -- "^$1=.*"; }

Z.B.:

> V=voodoo
sv V
V=voodoo

Problem: Hiermit werden die Definitionen der oben genannten Variablen nicht wie im aktuellen Kontext gedruckt, z. B. in einer interaktiven Shell-Eingabeaufforderung (oder FUNCNAME ist nicht definiert. Aber meine Funktion sagt mir die falschen Informationen:

> sv FUNCNAME
FUNCNAME=([0]="sv")

Eine Lösung, die ich mir ausgedacht habe, wurde von anderen in anderen Posts zu diesem Thema erwähnt. Für diesen speziellen Befehl zum Drucken von Variablendefn., Für den nur ein Argument erforderlich ist, habe ich Folgendes ausgeführt:

alias asv='(grep -- "^$(cat -)=.*" <(set)) <<<'

Welche gibt die richtige Ausgabe (keine) und Ergebnisstatus (falsch):

> asv FUNCNAME
> echo $?
1

Ich fühlte mich jedoch immer noch gezwungen, eine Lösung zu finden, die für eine beliebige Anzahl von Argumenten funktioniert.

Eine allgemeine Lösung, um willkürliche Argumente an einen Bash-Alias-Befehl zu übergeben:

# (I put this code in a file "alias-arg.sh"):

# cmd [arg1 ...] – an experimental command that optionally takes args,
# which are printed as "cmd(arg1 ...)"
#
# Also sets global variable "CMD_DONE" to "true".
#
cmd () { echo "cmd([email protected])"; declare -g CMD_DONE=true; }

# Now set up an alias "ac2" that passes to cmd two arguments placed
# after the alias, but passes them to cmd with their order reversed:
#
# ac2 cmd_arg2 cmd_arg1 – calls "cmd" as: "cmd cmd_arg1 cmd_arg2"
#
alias ac2='
    # Set up cmd to be execed after f() finishes:
    #
    trap '\''cmd "${CMD_ARGV[1]}" "${CMD_ARGV[0]}"'\'' SIGUSR1;
    #        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    #       (^This is the actually execed command^)
    #
    # f [arg0 arg1 ...] – acquires args and sets up trap to run cmd:
    f () {
        declare -ag CMD_ARGV=("[email protected]");  # array to give args to cmd
        kill -SIGUSR1 $$;             # this causes cmd to be run
        trap SIGUSR1;                 # unset the trap for SIGUSR1
        unset CMD_ARGV;               # clean up env...
        unset f;                      # incl. this function!
    };
    f'  # Finally, exec f, which will receive the args following "ac2".

Z.B.:

> . alias-arg.sh
> ac2 one two
cmd(two one)
>
> # Check to see that command run via trap affects this environment:
> asv CMD_DONE
CMD_DONE=true

Eine nette Sache an dieser Lösung ist, dass alle speziellen Tricks, die zum Behandeln von Positionsparametern (Argumenten) für Befehle verwendet werden, beim Erstellen des überfüllten Befehls funktionieren. Der einzige Unterschied besteht darin, dass die Array-Syntax verwendet werden muss.

Z.B.,

Wenn Sie "$ @" möchten, verwenden Sie "$ {CMD_ARGV [@]}".

Wenn Sie "$ #" möchten, verwenden Sie "$ {# CMD_ARGV [@]}".

Usw.

3
crobc1

Zum Aufnehmen von Parametern sollten Sie Funktionen verwenden!

$ @ Wird jedoch beim Erstellen des Alias ​​anstatt während der Ausführung des Alias ​​interpretiert, und das Escape-Zeichen für $ funktioniert auch nicht. Wie löse ich dieses Problem?

Sie müssen die Shell-Funktion anstelle eines Alias ​​verwenden, um dieses Problem zu beheben. Sie können foo wie folgt definieren:

function foo() { /path/to/command "[email protected]" ;}

OR

foo() { /path/to/command "[email protected]" ;}

Rufen Sie abschließend Ihr foo () mit der folgenden Syntax auf:

foo arg1 arg2 argN

Stellen Sie sicher, dass Sie Ihr foo () in die Datei ~/.bash_profile oder ~/.zshrc einfügen.

In Ihrem Fall wird dies funktionieren

function trash() { mv [email protected] ~/.Trash; }
2
Ahmad Awais

Funktionen sind in der Tat fast immer die Antwort, wie bereits ausführlich dargelegt und durch dieses Zitat aus der Manpage bestätigt: "In fast allen Fällen werden Aliase durch Shell-Funktionen abgelöst."

Der Vollständigkeit halber und weil dies nützlich sein kann (etwas leichtgewichtigere Syntax), kann angemerkt werden, dass, wenn die Parameter dem Alias ​​folgen, sie weiterhin verwendet werden können (obwohl dies nicht die Anforderung des OP adressiert). Dies lässt sich wahrscheinlich am einfachsten anhand eines Beispiels demonstrieren:

alias ssh_disc='ssh -O stop'

erlaubt mir, smth wie ssh_disc myhost einzugeben, das wie erwartet erweitert wird als: ssh -O stop myhost

Dies kann nützlich sein für Befehle, die komplexe Argumente enthalten (mein Gedächtnis ist nicht mehr das, was es braucht ...)

1
sxc731

Sowohl Funktionen als auch Aliase können Parameter verwenden, wie andere hier gezeigt haben. Darüber hinaus möchte ich auf einige andere Aspekte hinweisen:

1. Funktion läuft in einem eigenen Bereich, Alias ​​teilt den Bereich

Es kann nützlich sein, diesen Unterschied zu kennen, wenn Sie etwas verstecken oder bloßstellen müssen. Dies legt auch nahe, dass eine Funktion die bessere Wahl für die Verkapselung ist.

function tfunc(){
    GlobalFromFunc="Global From Func" # Function set global variable by default
    local FromFunc="onetwothree from func" # Set a local variable

}

alias talias='local LocalFromAlias="Local from Alias";  GlobalFromAlias="Global From Alias" # Cant hide a variable with local here '
# Test variables set by tfunc
tfunc # call tfunc
echo $GlobalFromFunc # This is visible
echo $LocalFromFunc # This is not visible
# Test variables set by talias
# call talias
talias
echo $GlobalFromAlias # This is invisible
echo $LocalFromAlias # This variable is unset and unusable 

Ausgabe:

bash-3.2$     # Test variables set by tfunc
bash-3.2$     tfunc # call tfunc
bash-3.2$     echo $GlobalFromFunc # This is visible
Global From Func
bash-3.2$     echo $LocalFromFunc # This is not visible

bash-3.2$     # Test variables set by talias
bash-3.2$     # call talias
bash-3.2$     talias
bash: local: can only be used in a function
bash-3.2$     echo $GlobalFromAlias # This is invisible
Global From Alias
bash-3.2$ echo $LocalFromAlias # This variable is unset and unusable

2. Wrapper-Skript ist eine bessere Wahl

Es ist mir mehrmals passiert, dass ein Alias ​​oder eine Funktion nicht gefunden werden kann, wenn Anmelden über ssh oder wenn ein Benutzername oder eine Mehrbenutzerumgebung geändert wird. Es gibt Tipps und Tricks bei der Beschaffung von Punktedateien oder diese interessante mit Alias: alias sd='Sudo ' lässt diesen nachfolgenden Alias ​​alias install='sd apt-get install' wie erwartet funktionieren (beachten Sie den zusätzlichen Platz in sd='Sudo '). In solchen Fällen funktioniert ein Wrapper-Skript jedoch besser als eine Funktion oder ein Alias. Der Hauptvorteil eines Wrapper-Skripts besteht darin, dass es unter dem vorgesehenen Pfad (d. H./Usr/loca/bin /) sichtbar/ausführbar ist, unter dem eine Funktion/ein Alias ​​bezogen werden muss, bevor es verwendet werden kann. Wenn Sie beispielsweise eine Funktion in ein ~/.bash_profile oder ~/.bashrc für bash einfügen und später zu einer anderen Shell wechseln (d. H. zsh), ist die Funktion nicht mehr sichtbar. Wenn Sie sich nicht sicher sind, ist ein Wrapper-Skript immer die zuverlässigste und portabelste Lösung.

1
biocyberman