J'utilise la commande suivante:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
Et je reçois l'erreur:
-bash: /bin/cp: Argument list too long
J'ai aussi essayé:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
Toujours obtenu -bash: / bin / ls: liste d'arguments trop longue
Des idées?
linux
bash
unix-shell
icelizard
la source
la source
ls
n'est pas conçu pour faire ce genre de chose. Utilisezfind
.ls
n'est surtout pas conçu pour cela: mywiki.wooledge.org/ParsingLsRéponses:
* .jpg se développe en une liste plus longue que le shell ne peut gérer. Essayez ceci à la place
la source
Il y a une limite maximale à la longueur d'une liste d'arguments pour les commandes système - cette limite est spécifique à la distribution en fonction de la valeur de
MAX_ARG_PAGES
la compilation du noyau et ne peut pas être modifiée sans recompilation du noyau.En raison de la façon dont le globbing est géré par le shell, cela affectera la plupart des commandes système lorsque vous utilisez le même argument ("* .jpg"). Étant donné que le glob est d'abord traité par le shell, puis envoyé à la commande, la commande:
est essentiellement le même pour le shell que si vous écriviez:
Si vous traitez avec beaucoup de jpegs, cela peut devenir ingérable très rapidement. Selon votre convention de dénomination et le nombre de fichiers que vous devez réellement traiter, vous pouvez exécuter la commande cp sur un sous-ensemble différent du répertoire à la fois:
Cela pourrait fonctionner, mais exactement son efficacité est basée sur la façon dont vous pouvez diviser votre liste de fichiers en blocs globbables pratiques.
Globbable. J'aime ce mot.
Certaines commandes, telles que find et xargs , peuvent gérer de grandes listes de fichiers sans créer de listes d'arguments douloureusement dimensionnées.
L'argument -exec exécutera le reste de la ligne de commande une fois pour chaque fichier trouvé par find , en remplaçant le {} par chaque nom de fichier trouvé. Étant donné que la commande cp n'est exécutée que sur un fichier à la fois, la limite de la liste d'arguments n'est pas un problème.
Cela peut être lent car vous devez traiter chaque fichier individuellement. L'utilisation de xargs pourrait fournir une solution plus efficace:
xargs peut prendre la liste complète des fichiers fournie par find , la décomposer en listes d'arguments de tailles gérables et exécuter cp sur chacune de ces sous-listes.
Bien sûr, il est également possible de simplement recompiler votre noyau, en définissant une valeur plus élevée pour
MAX_ARG_PAGES
. Mais recompiler un noyau est plus de travail que je ne veux l'expliquer dans cette réponse.la source
xargs
semble être beaucoup plus efficace, car le nombre d'appels de commande qui en résulte est beaucoup plus petit. Dans mon cas, je vois des performances 6 à 12 fois meilleures lors de l'utilisation,args
puis lorsque l'utilisation d'une-exec
solution avec un nombre croissant de fichiers augmente l'efficacité.Cela se produit car votre expression générique (
*.jpg
) dépasse la limite de longueur d'argument de ligne de commande lorsqu'elle est développée (probablement parce que vous avez beaucoup de fichiers .jpg sous/home/ftpuser/public_html/ftparea
).Il existe plusieurs façons de contourner cette limitation, comme l'utilisation de
find
ouxargs
. Jetez un œil à cet article pour plus de détails sur la façon de procéder.la source
Comme l'a souligné GoldPseudo, il y a une limite au nombre d'arguments que vous pouvez transmettre à un processus que vous générez. Voir sa réponse pour une bonne description de ce paramètre.
Vous pouvez éviter le problème en ne passant pas trop d'arguments au processus ou en réduisant le nombre d'arguments que vous passez.
Une boucle for dans le shell, find et ls, grep et une boucle while font tous la même chose dans cette situation -
et
et
tous ont un programme qui lit le répertoire (le shell lui-même, find et ls) et un programme différent qui prend en fait un argument par exécution et parcourt toute la liste des commandes.
Maintenant, cela sera lent car le rm doit être bifurqué et exécuté pour chaque fichier qui correspond au modèle * .jpg.
C'est là que xargs entre en jeu. xargs prend une entrée standard et pour chaque N (pour freebsd c'est 5000 par défaut) lignes, il génère un programme avec N arguments. xargs est une optimisation des boucles ci-dessus car il vous suffit de bifurquer des programmes 1 / N pour itérer sur l'ensemble des fichiers qui lisent les arguments de la ligne de commande.
la source
Il y a un nombre maximum d'arguments qui peuvent être spécifiés pour un programme, bash étend * .jpg à beaucoup d'arguments à cp. Vous pouvez le résoudre en utilisant find, xargs ou rsync etc.
Jetez un oeil ici sur xargs et trouvez
/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names
la source
Le glob «*» s'étend à trop de noms de fichiers. Utilisez plutôt find / home / ftpuser / public_html -name '* .jpg'.
la source
L'utilisation de l'
+
option pourfind -exec
accélérera considérablement l'opération.L'
+
option doit{}
être le dernier argument, donc utiliser l' option-t /your/destination
(ou--target-directory=/your/destination
) pour lacp
faire fonctionner.De
man find
:Edit : réarrangement des arguments en cp
la source
cp
pour corriger cette erreur.Il semble que vous ayez trop de
*.jpg
fichiers dans ce répertoire pour les mettre tous sur la ligne de commande à la fois. Tu pourrais essayer:Vous devrez peut-être vérifier
man xargs
votre implémentation pour voir si le-I
commutateur est correct pour votre système.En fait, avez-vous vraiment l'intention de copier ces fichiers au même endroit où ils se trouvent déjà?
la source
ls
aura le même problème! J'ai changé pourfind
ce qui ne le sera pas.Accéder au dossier
et exécutez ce qui suit:
De cette façon, si le dossier 'ftparea' a des sous-dossiers, cela pourrait être un effet négatif si vous n'en voulez que les fichiers '* .jpg', mais s'il n'y a pas de sous-dossiers, cette approche sera certainement beaucoup plus rapide que en utilisant find et xargs
la source