J'essaie d'exécuter une commande similaire à celle ci-dessous dans un script bash. Il doit rechercher dans tous les sous-dossiers de $sourcedir
et copier tous les fichiers d'un certain type au niveau racine de $targetdir
.
#!/bin/bash
# These are set as arguments to the script, not hard-coded
sourcedir="/path/to/sourcedir"
targetdir="/path/to/targetdir"
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2/`basename "$1"`"' "{}" "$targetdir" \;
Cela semble être assez proche, sauf que {}
n'est pas passé en tant que $2
de-exec sh -c ...
Je voudrais le faire aussi près que possible de la "bonne façon", avec une tolérance pour les caractères spéciaux dans les noms de fichiers (en particulier les guillemets simples).
Edit: Je vois des gens suggérer d'utiliser xargs
ou de chaîner des arguments. J'avais l'impression que ce n'était acceptable que pour un nombre limité d'arguments. Si j'ai, par exemple, des milliers de fichiers .jpg que j'essaie de copier d'un certain nombre de répertoires de la galerie dans un répertoire de diaporamas géants, les solutions d'enchaînement des arguments fonctionneront-elles toujours?
Edit 2: Mon problème était qu'il me manquait un _
avant ma première option pour sh dans la -exec
commande. Pour toute personne curieuse de savoir comment faire fonctionner la commande find, ajoutez le _
et tout ira bien:
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2"' _ "{}" "$targetdir" \;
J'ai accepté une réponse ci-dessous, car elle accomplit la même tâche, mais est plus efficace et élégante.
la source
xargs
a été créé, pour gérer automatiquement d'énormes quantités d'arguments sur des commandes régulières qui avaient des limites. De plus, la plupart des limites maximales d'arguments ont été considérablement améliorées pour les utilitaires GNU standard. Vous verrez également un avantage en termes de performances, en évitant toutes ces fourchettes de processus, qui sont pertinentes sur des milliers de fichiers.Réponses:
Vous souhaitez copier des fichiers d'un type spécifique, dans un répertoire spécifique? Il vaut mieux le faire
xargs
, et vous n'en avez même pas besoinsh
. C'est une façon plus appropriée de le faire, devrait également fonctionner plus efficacement.Si vous devez gérer des noms de fichiers spéciaux, utilisez-les
NULL
comme séparateurla source
-print0
àfind
et-0
àxargs
NULL
n'est pas nécessaire si vous utilisez'{}'
, c'est important quand vous ne l'utilisez pas. Le véritable avantage entre l'un et l'autre, autre que laPOSIX
conformité, est la performance.Vous devez passer
{}
comme argument au shell puis faire une boucle sur chaque argument.Remarque : La façon dont cela fonctionne est que le premier argument d'un shell est le nom du shell , nous pouvons l'exploiter en passant le nom en tant que
$targetdir
, puis utiliser le paramètre spécial$0
à l'intérieur du script shell pour accéder à ce répertoire cible.la source
"$targetdir"
n'est pas développé à l'intérieur de guillemets simples.Si vous ne croyez pas à l'église de xargs:
Explication:
copie b, c et d dans le répertoire cible a.
invoque la commande sur un grand nombre de fichiers à la fois, pas l'un après l'autre (ce qui est standard, si vous utilisez à la
";"
place de+
). C'est pourquoi vous devez tirer le répertoire cible vers l'avant et le marquer explicitement comme cible.Cela fonctionne pour gnu-find et peut-être pas pour d'autres implémentations de find. Bien sûr, il s'appuie également sur le drapeau -t.
TechZilla est bien sûr à l'extrême droite, car il
sh
n'est pas nécessaire d'invoquer cp.Si vous n'utilisez pas
xargs
, ce qui est la plupart du temps inutile en combinaison avecfind
, vous êtes sauvé de l'apprentissage du drapeau-print0
et-0
.la source
xargs
. Le plus grand exemple, que faire si vous ne trouvez pas de fichiers? J'utilise xargs à la place desfor
boucles générales tout le temps,find
est beaucoup plus petit. De plus,find
ne prend en charge que+
si vous utilisez GNUfind
, il n'est pas défini dans POSIX. Donc, alors que vous devriez vous sentir libre de préférerfind
seul, il ne fait pas tout ce que fait xargs. Lorsque vous considérez GNU,xargs
vous obtenez également-P
ce qui est multi-core. Cela vaut la peine d'apprendrexargs
malgré tout.la source