Qui s'occupe de l'étoile * en écho *

15

Qui s'occupe (interprète) le * dans

echo *

L'écho voit-il l'étoile ou le shell s'en occuper et renvoyer une liste de nom de fichier.

Qu'en est-il de

cp temp temp*
faressoft
la source
14
Cela varie. Coques Unix ou Windows?
user1686
@grawity Unix shells. Désolé, je n'ai pas mentionné cela.
faressoft
Pour Unix, les réponses ci-dessous sont correctes. (Sous Windows, cela se fait par des programmes individuels - mais généralement automatiquement par la bibliothèque d'exécution avant main ().)
user1686

Réponses:

24

bash (ou tout ce que vous utilisez comme shell), est la première chose à lire n'importe quelle entrée, et commencera à interpréter les caractères spéciaux tels que ?et *. *est étendu à toutes les correspondances dans le CWD , ce qui signifie que l'astérisque est remplacé par lesdites correspondances.

Dans la plupart des cas, c'est assez avancé, mais cela peut parfois conduire à des cas confus.

Considérer ce qui suit. Un répertoire a ce contenu:

  • test (fichier normal)
  • test1 (répertoire)
  • test2 (répertoire)
  • test3 (répertoire)

Si vous tapez alors mv *quelque chose qui semble bizarre, cela se produit: test3est là, mais le reste a disparu. Bien que bizarre au début, cela a du sens une fois que vous comprenez à quoi bash passe réellement mv. En raison de l'astérisque, bash interprète mv *comme mv test test1 test2 test3, et lorsque mv obtient cette liste, il supposera que le dernier argument est la destination, qui est l'endroit où tous les fichiers auraient été déplacés.

Quant aux commandes que vous avez listées:

  • echo * peut fonctionner comme un pauvre ls . Le shell étendra l'astérisque à tout ce qui se trouve dans ce répertoire, et comme je suis sûr que vous le savez déjà, echorésonnera littéralement tout ce qui lui est passé en tant qu'arguments.
  • cp temp temp*se comportera un peu comme la mvcommande que j'ai décrite ci-dessus, à moins qu'il n'y ait qu'un seul répertoire nommé temp, auquel cas le nom de la source et de la destination est le même, c'est-à-dire qu'il ne fera rien.
Jarmund
la source
8
Il n'y a rien de "pauvre" à utiliser à la *place de ls. Par exemple, for f in *; doest plus fiable que for f in $(ls)si un nom de fichier contient un espace ou un caractère global. (Cependant, il échouera s'il n'y a pas de fichiers dans le CWD, vous devez donc vérifier ce cas.)
rici
1
@rici C'est pour ça shopt nullglob.
un CVn le
3
Quant à echo *, cette astuce peut vous sauver dans certains cas.
un CVn du
2
Réaction avec: fichiers précédés de "-" dans des dossiers arbitraires qui déclenchent des commutateurs indésirables. Les supprimer n'est pas très amusant jusqu'à ce que vous réalisiez que rm ./-stupidfile fonctionne.
ǝɲǝɲbρɯͽ
1
@ ǝɲǝɲbρɯͽ J'ai remarqué qu'une fois j'avais besoin de supprimer le contenu d'un répertoire contenant des fichiers avec le nom de fichier représentant les positions dans un système de coordonnées, de -1024x-1024 à 1024x1024. C'est là que j'ai appris pour la première fois à m'échapper.
Jarmund
5

Comme déjà indiqué, le shell se développe *afin de echorecevoir comme arguments tout ce que le shell trouve dans le répertoire courant. Cependant, notez que si l'expansion ne mène à rien, c'est-à-dire dans ce cas si le répertoire ne contient aucun fichier non caché, le *reste inchangé et transmis tel quel à la commande appelée (sauf si des options non standard sont utilisées avec certains shells comme bash.) echo *ne va pas se comporter comme un pauvre lscar le premier n'imprimera rien tandis que le second imprimera *.

De même, cp /tmp/temp temp*créera un fichier nommé temp*dans le répertoire courant s'il n'y a pas encore au moins un fichier dont le nom commence par temp.

Enfin, si vous souhaitez que le *soit inchangé quel que soit le cas, vous pouvez le protéger de l'expansion à l'aide de guillemets simples, de guillemets '*'doubles "*"ou d'une barre oblique inverse \*.

jlliagre
la source
4

Dans Bash, le shell s'en occupe. Vous voyez que si vous essayez même *sans écho

Remarque - sur la base de certains commentaires, je suggère lors de l'exécution de * ENTER, de créer un répertoire et d'utiliser la commande tactile pour créer certains fichiers, et assurez-vous qu'aucun d'entre eux, ou du moins assurez-vous que le premier par ordre alphabétique, n'est pas le nom de n'importe quel script ou commande dans le chemin.

$ *
bash: a: command not found

$ echo *
a a.aa a.ab a.b a.htm a.tx

Donc ls * un peu un cliché

Sous Windows, *est géré par la commande, ce dir *.*n'est donc pas un cliché.

Remarque - En voyant certains commentaires, j'ajouterais, il y a un risque de courir * puis ENTER. Si vous avez un fichier appelé rm qui est le premier dans la liste des répertoires, il est dangereux car tout ce qui se trouve après serait supprimé. En outre, et cela est moins improbable, si le premier fichier dans la liste des répertoires est le nom d'un script dans le chemin d'accès, il l'exécutera.

barlop
la source
4
Notez qu'il pourrait y avoir un fichier nommé rm, bien sûr.
Volker Siegel
1
... et un autre appelé -rf
ǝɲǝɲbρɯͽ
1
@ ǝɲǝɲbρɯͽ pouvez-vous avoir un fichier dont le nom de fichier est -rf? J'ai essayé touch -rfet touch \-rfça ne le crée pas.
barlop
@barlop J'ai commenté ci-dessus; le gui (comme gedit) les gère très bien, mais comme le shell (au moins bash) le traverse, il faut ./ devant. Si jamais vous créez accidentellement un tel fichier, rm essaie de suggérer, mais si ce n'est pas le cas: j'espère que cela ne se retrouvera que dans un dossier temporaire avec des enfants jetables.
ǝɲǝɲbρɯͽ
@ ǝɲǝɲbρɯͽ Je ne comprends pas du tout ce que vous voulez dire, je me demande comment pouvez-vous créer un fichier nommé -rf? (Je comprends le danger d'un fichier appelé rm et d'un fichier appelé -rf, et le problème de taper * et de pousser enter dans un dossier important, je n'ai pas l'intention de le faire)
barlop
-1

Le shell effectue plusieurs extensions avant que les arguments ne soient remis à la commande.

Voir aussi https://www.gnu.org/software/bash/manual/bashref.html#Simple-Command-Expansion

Pas spécifique à bash, voir http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01

glenn jackman
la source
Techniquement, ce que vous écrivez est correct, mais sans les liens, cette réponse ne fait vraiment rien pour répondre à la question. Pensez à incorporer les détails pertinents.
un CVn le
@ MichaelKjörling Je suis d'accord avec les liens, mais l'OP a simplement demandé si le shell ou la commande elle-même gérait les arguments. La réponse de Glenn indique simplement que le shell les gère, c'est donc une réponse acceptable à la question.
slhck
@slhck C'est pourquoi je ne me suis pas signalé comme NAA: il reste quelque chose qui résout la question après avoir supprimé les liens. Cela ne signifie pas que c'est une bonne réponse à mon avis . (Je vois maintenant que mon commentaire initial pourrait être interprété autrement; pour cela, je m'excuse, mais je pense toujours qu'il a suffisamment de valeur pour le laisser là où il est.)
un CVn du
@ MichaelKjörling D'accord. Je viens de laisser le commentaire à ceux qui l' ont (et le feront) comme NAA.
slhck