GNU/Linux >> Tutoriels Linux >  >> Linux

Pourquoi find -exec mv {} ./target/ + ne fonctionne-t-il pas ?

J'ai rencontré le même problème sur Mac OSX , en utilisant un ZSH shell :dans ce cas, il n'y a pas de -t option pour mv , j'ai donc dû trouver une autre solution. Cependant, la commande suivante a réussi :

find .* * -maxdepth 0 -not -path '.git' -not -path '.backup' -exec mv '{}' .backup \;

Le secret était de citer les accolades . Pas besoin que les accolades soient à la fin du exec commande.

J'ai testé sous Ubuntu 14.04 (avec BASH et ZSH shells), cela fonctionne de la même manière.

Cependant, lors de l'utilisation du + signe, il semble bien qu'il doive être à la fin du exec commande.


La page de manuel (ou le manuel GNU en ligne) explique à peu près tout.

trouver -exec commande {} \;

Pour chaque résultat, command {} est exécuté. Toutes les occurrences de {} sont remplacés par le nom du fichier. ; est préfixé par une barre oblique pour empêcher le shell de l'interpréter.

commande find -exec {} +

Chaque résultat est ajouté à command et exécuté ensuite. En tenant compte des limitations de longueur de commande, je suppose que cette commande peut être exécutée plusieurs fois, avec la page de manuel qui me soutient :

le nombre total d'invocations de la commande sera bien inférieur au nombre de fichiers correspondants.

Notez cette citation de la page de manuel :

La ligne de commande est construite de la même manière que xargs construit ses lignes de commande

C'est pourquoi aucun caractère n'est autorisé entre {} et + sauf pour les espaces blancs. + fait find détecter que les arguments doivent être ajoutés à la commande comme xargs .

La solution

Heureusement, l'implémentation GNU de mv peut accepter le répertoire cible comme argument, avec soit -t ou le paramètre plus long --target . Son utilisation sera :

mv -t target file1 file2 ...

Votre find commande devient :

find . -type f -iname '*.cpp' -exec mv -t ./test/ {} \+

À partir de la page de manuel :

-exec commande;

Exécutez la commande ; true si le statut 0 est renvoyé. Tous les arguments suivants à rechercher sont considérés comme des arguments de la commande jusqu'à ce qu'un argument consistant en ';' est rencontré. La chaîne `{}' est remplacée par le nom du fichier en cours de traitement partout où il apparaît dans les arguments de la commande, pas seulement dans les arguments où il est seul, comme dans certaines versions de find. Ces deux constructions peuvent avoir besoin d'être échappées (avec un `\') ou entre guillemets pour les protéger de l'expansion par le shell. Voir la section EXEMPLES pour des exemples d'utilisation de l'option -exec. La commande spécifiée est exécutée une fois pour chaque fichier correspondant. La commande est exécutée dans le répertoire de départ. Il existe des problèmes de sécurité inévitables entourant l'utilisation de l'action -exec; vous devriez utiliser l'option -execdir à la place.

-exec commande {} +

Cette variante de l'action -exec exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est construite en ajoutant chaque nom de fichier sélectionné à la fin ; le nombre total d'invocations de la commande sera bien inférieur au nombre de fichiers correspondants. La ligne de commande est construite de la même manière que xargs construit ses lignes de commande. Une seule instance de `{}' est autorisée dans la commande. La commande est exécutée dans le répertoire de départ.


L'équivalent standard de find -iname ... -exec mv -t dest {} + pour find implémentations qui ne prennent pas en charge -iname ou mv implémentations qui ne prennent pas en charge -t consiste à utiliser un shell pour réorganiser les arguments :

find . -name '*.[cC][pP][pP]' -type f -exec sh -c '
  exec mv "[email protected]" /dest/dir/' sh {} +

En utilisant -name '*.[cC][pP][pP]' , nous évitons également de dépendre des paramètres régionaux actuels pour décider quelle est la version majuscule de c ou p .

Notez que + , contrairement à ; n'est pas spécial dans un shell et n'a donc pas besoin d'être entre guillemets (bien que les guillemets ne nuisent pas, sauf bien sûr avec des shells comme rc qui ne prennent pas en charge \ en tant qu'opérateur de cotation).

Le / de fin en /dest/dir/ est tel que mv échoue avec une erreur au lieu de renommer foo.cpp à /dest/dir dans le cas où un seul cpp le fichier a été trouvé et /dest/dir n'existait pas ou n'était pas un répertoire (ou un lien symbolique vers le répertoire).


Linux
  1. Pourquoi /bin/sh pointe-t-il vers /bin/dash et non /bin/bash ? ?

  2. Comment savoir à partir de quel dossier un processus est en cours d'exécution ?

  3. Pourquoi cette regex ne fonctionne-t-elle pas sous Linux ?

  4. Pourquoi mettre des choses autres que /home sur une partition séparée ?

  5. /sys/ documentation ?

Linux :Différence entre /dev/console , /dev/tty et /dev/tty0 ?

Bash =~ Regex et Https://regex101.com/?

Linux – /sbin/init n'existe pas ?

echo ou print /dev/stdin /dev/stdout /dev/stderr

Pourquoi < ou > sont-ils nécessaires pour utiliser /dev/tcp

Les sites Web doivent-ils vivre dans /var/ ou /usr/ selon l'utilisation recommandée ?