web-dev-qa-db-fra.com

Confus au sujet de grep et du caractère générique *

J'exécute la commande suivante afin de trouver tous les fichiers/répertoires qui n'ont rien à voir avec "flash_drive_data":

find . -not -path './flash_drive_data*' | grep "./*flash*"

Il y a quelques choses que j'ai essayées qui me déroutent:

1- Lorsque j'exécute la commande ci-dessus, j'obtiens quelques hits "partiels" (c'est-à-dire qu'ils ne correspondent pas complètement au *flash* modèle. Par exemple:

./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/cli.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/signals.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/templating.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/sessions.pyi
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/json
./.local/lib/python3.7/site-packages/jedi/third_party/typeshed/third_party/2and3/flask/json/tag.pyi

Le 3/flas à la fin est en surbrillance

2- Quand j'ai remplacé grep "*flash*" avec juste grep "*", Je m'attendais à ce que tous les fichiers soient retournés par find, mais je n'en ai aucun. Pourquoi? Ensuite, quand j'ai fait grep "**" Je crois avoir tous les fichiers (ou du moins je pense que je l'ai fait). Encore une fois, pourquoi est-ce?

3- Enfin, l'objectif de ce que je faisais ci-dessus était de m'assurer que lorsque je courrais find . -not -path './flash_drive_data*' Je n'obtenais rien lié à flash_drive_data. Il semblait que je l'ai fait (avec un comportement inattendu avec grep comme je l'ai expliqué ci-dessus). Cependant, quand j'ai couru: find . -not -path './flash_drive_data*' -exec tar cfv home.tar.bz '{}' + J'obtenais une sortie comprenant des choses comme:

./flash_drive_data/index2/ask-sdk-core/dist/dispatcher/error/handler/

donc les fichiers flash_drive_data étaient inclus.

4
find . -not -path './flash_drive_data*' | grep "./*flash*"

La chose ici est que grep utilise des expressions régulières, tandis que find -path utilise les correspondances de modèle de style Shell glob. L'astérisque a une signification différente dans ces deux cas.

L'expression régulière ./*flash* correspond d'abord à n'importe quel caractère (.), puis zéro ou plusieurs barres obliques (/*), puis une chaîne littérale flas, puis n'importe quel nombre (zéro ou plus) de h caractères. 3/flas correspond à cela (avec zéro fois h), et ainsi par exemple reflash (avec zéro fois /).

Vous pouvez simplement utiliser grep flash à la place, étant donné qu'il correspond n'importe où dans l'entrée, les parties "correspond à tout" ne sont donc pas nécessaires.

Ou utiliser find -path './*flash*' -and -not -path './flash_drive_data*'

Quand j'ai remplacé grep "*flash*" avec juste grep "*", J'ai [pas de correspondance].

Puisque l'astérisque signifie "n'importe quel nombre de l'atome précédent", il n'est pas vraiment bien défini ici. grep interprète cela comme un astérisque littéral, mais ce devrait être une erreur.

Cependant, quand j'ai couru: find . -not -path './flash_drive_data*' -exec tar cfv home.tar.bz '{}' + J'obtenais une sortie comprenant des choses comme:

./flash_drive_data/index2/ask-sdk-core/dist/dispatcher/error/handler/

donc flash_drive_data les fichiers étaient inclus.

Notez que tar stocke les fichiers récursivement, et la première sortie de ce find est . pour le répertoire courant, donc tout sera stocké. Vous voudrez peut-être utiliser ! -type d avec find pour exclure les répertoires de la sortie, ou (mieux), regardez le -exclude=PATTERN options à tar.

3
ilkkachu

Vous confondez la signification différente de * pour Expansion du nom de fichier du shell et Posix Basic Regex .

Dans Regex, * est le quantificateur du caractère devant lui, donc h* signifie 0 ou plusieurs occurrences de h. Si vous voulez "n'importe quel nombre de n'importe quel caractère", utilisez .*.

grep '*' rechercherait le littéral * car il n'y a rien devant lui à quantifier, tandis que grep '**' souhaiterait 0 occurrence ou plus de *, donc tout ira comme 0 occurrence de quelque chose toujours.


Quoi qu'il en soit , vous devriez plutôt utiliser find avec l'argument -path "*/flash/*" au lieu de grep la sortie de find.

14
pLumo