Quel est l'argument manquant pour -exec?

15

J'utilise la commande suivante pour effacer un répertoire, des fichiers et des répertoires de plus de 30 jours, et les déplacer vers un répertoire d'archives que je peux supprimer après quelques semaines si personne ne demande à récupérer leurs fichiers. Le répertoire cible a des sous-répertoires par nom d'utilisateur, tout comme le répertoire d'archivage.

Voici la commande que j'utilise:

find /path/to/directory/username/ -mtime +30 -exec mv "{}" /path/to/archive/username/ \;

J'ai proposé une version modifiée de ce pour répondre à une question demander ubuntu, un autre utilisateur a modifié le code pour changer la fin de la ligne \;pour +qu'il est plus rapide (et plus juste?). Vois ici

Cependant, l'utilisation +de cette manière fonctionne si la -execcommande est ls -lhmais pas dans la commande réelle que j'utilise. Si je l'essaye avec, +j'obtiens un message d'erreur:

find: missing argument to '-exec'

Je ne comprends pas pourquoi il se comporte de cette façon, ni quelle serait la commande correcte. S'il vous plaît ne postez pas seulement une correction de commande, j'aimerais comprendre plutôt que de simplement suivre une suggestion aveuglément.

Arronical
la source
Parlez-vous de cette réponse ? Cela pourrait expliquer pourquoi
Wilf
Merci @Wilf, j'ai mis à jour pour montrer sur quelle réponse la modification s'est produite. Le lien que vous avez fourni contient un autre lien qui l'explique d'une manière que mon cerveau peut gérer.
Arronical
Merci @souravc d'une manière brillamment cyclique cette question est posée par l'utilisateur qui a édité ma commande! Enfin, je reçois qu'il +fournit plusieurs arguments à la même commande, mais je mvne peux pas y faire face!
Arronical
@Arronical mv can, voyez ma réponse ^^
chaos

Réponses:

19

L'utilisateur de ce message peut dire que le +signe à la fin d'une -execcommande est plus rapide, mais pas pourquoi.

Supposons que la findcommande retourne les fichiers suivants:

/path/to/file1
/path/to/file2
/path/to/file3

La -execcommande normale ( -exec command {} \;) s'exécute une fois pour chaque fichier correspondant. Par exemple:

find ... -exec mv {} /target/ \;

Exécute:

mv /path/to/file1 /target/
mv /path/to/file2 /target/
mv /path/to/file3 /target/

Si vous utilisez le +signe ( -exec command {} +), la commande est créée en ajoutant plusieurs fichiers correspondants à la fin de la commande. Par exemple:

find ... -exec mv -t /target/ {} +

Exécute:

mv -t /target/ /path/to/file1 /path/to/file2 /path/to/file3

Pour utiliser +correctement l' indicateur, l'argument à traiter doit être à la fin de la commande, pas au milieu. C'est pourquoi findTrows missing argument to '-exec'dans votre exemple; il manque la fermeture {}.

le chaos
la source
Je me suis toujours demandé pourquoi find -execrequiert que ce {}soit le dernier argument, lorsqu'il est utilisé avec +. Quelqu'un sait pourquoi cette décision de conception a été prise, au lieu de laisser fonctionner des constructions comme la ligne de commande de l'OP?
Peter Cordes
11

L'utilisateur a expliqué sa modification ....

Le terminateur de l'exécuteur '+' est plus rapide que '\;'  voir /ubuntu/558817/what-is-the-difference-between-using-and-in-exec-command;  et la création d'un fichier de sauvegarde à partir du fichier d'origine est une bonne idée

... en utilisant ce lien . Je pense qu'au fond, au lieu d'utiliser plusieurs commandes, il envoie tous les noms de fichiers à une seule instance de commande, pour accélérer les choses. Voici un exemple d' ici :

L'utilisation de -exec avec un point-virgule ( find . -exec ls '{}' \;), exécutera

ls file1
ls file2
ls file3

Mais si vous utilisez un signe plus à la place ( find . -exec ls '{}' \+), tous les noms de fichiers seront passés comme arguments à une seule commande:

ls file1 file2 file3

Il existe d'autres formulaires disponibles en utilisant ;et +aussi (à partir d' ici :)

Par conséquent, l'exemple de syntaxe suivant est autorisé pour la commande find:

find . -exec echo {} \;
find . -exec echo {} ';'
find . -exec echo {} ";"
find . -exec echo {} \+
find . -exec echo {} +

CEPENDANT, je ne suis pas sûr que cela fonctionnera de toute façon avec la commande move, comme c'est la syntaxe mv [OPTION]... SOURCE DEST, à moins que l' -toption ou similaire ne soit utilisée. Cependant, cela devrait fonctionner lssans options supplémentaires, etc. car ils peuvent comprendre quand plusieurs noms de fichiers sont donnés. Il +peut également être nécessaire d’échapper (c.-à-d. \+)

Wilf
la source
Les deux grandes réponses, mais je dois donner au chaos d'être un peu plus rapide et d'expliquer les mv -tdeux + 1!
Arronical