Quand tu crées un programme pour qu'il effectue une tâche, tu peux le prévoir pour que les élements nécessaire à sa tâche lui soient passés lors de l'appel. Exemple le programme "cp" recevra deux éléments de travail: la source et la destination.
Ces éléments sont passés après le nom du programme et avant le <return>. On les nommes "arguments du programme" => cp toto titi.
Du côté programme, ces élements sont stockés dans des variables numérotées "$1", "$2", "$3", etc. qu'on nomme "paramètres de position" de par l'évidente corrélation entre les numéros des variables (1, 2, 3, etc) et la liste des arguments reçu (premier, second, troisième, etc). Ainsi dans l'exemple, "$1" contient "toto" et "$2" contient "titi". Plus "$#" qui contient le nombre d'arguments (ici 2), plus "$*" qui contient tous les arguments sous forme de chaine unique (donc "toto titi") et "$@" qui contient tous les arguments sous forme de chaines individuelles (donc "toto" "titi"). Plus "$0" qui contient le nom du programme tel qu'il a été invoqué en ligne de commande (ici "cp")
Ce stockage est automatique. C'est bash qui le fait lors de l'appel.
La commande set permet de réaffecter manuellement toutes ces variables. Si par exemple tu tapes l'instruction set xxx yyy zzz alors avant l'instruction tu as "$1" qui contient "toto", après l'instruction tu as "$1" qui contient "xxx" (et pareil pour tous les autres). Sauf "$0" qui reste inchangé.
Ca peut être utile par exemple pour explorer ton chemin pwd. Tu tapes IFS=/ set "$(pwd)" et tu as tout ton pwd explosé dans $1, $2, $3, etc...