Estoy usando el siguiente comando:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
Y recibo el error:
-bash: /bin/cp: Argument list too long
También he intentado:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
Todavía tengo -bash: / bin / ls: la lista de argumentos es demasiado larga
¿Algunas ideas?
linux
bash
unix-shell
icelizard
fuente
fuente
ls
no está diseñado para hacer este tipo de cosas. Usofind
.ls
es sobre todo que no está diseñado para hacer esto: mywiki.wooledge.org/ParsingLsRespuestas:
* .jpg se expande a una lista más larga de lo que el shell puede manejar. Intenta esto en su lugar
fuente
Existe un límite máximo para la duración de una lista de argumentos para los comandos del sistema: este límite es específico de la distribución según el valor de
MAX_ARG_PAGES
cuándo se compila el núcleo, y no se puede cambiar sin volver a compilar el núcleo.Debido a la forma en que el shell maneja el globbing, esto afectará a la mayoría de los comandos del sistema cuando use el mismo argumento ("* .jpg"). Dado que el shell primero procesa el glob y luego lo envía al comando, el comando:
es esencialmente lo mismo para el shell como si escribieras:
Si está lidiando con muchos archivos JPEG, esto puede volverse inmanejable muy rápido. Dependiendo de su convención de nomenclatura y la cantidad de archivos que realmente tiene que procesar, puede ejecutar el comando cp en un subconjunto diferente del directorio a la vez:
Esto podría funcionar, pero exactamente qué tan efectivo sería se basa en qué tan bien puede dividir su lista de archivos en convenientes bloques globbables.
Globbable Me gusta esa palabra
Algunos comandos, como find y xargs , pueden manejar grandes listas de archivos sin hacer listas de argumentos de gran tamaño.
El argumento -exec ejecutará el resto de la línea de comando una vez para cada archivo encontrado por find , reemplazando el {} con cada nombre de archivo encontrado. Dado que el comando cp solo se ejecuta en un archivo a la vez, el límite de la lista de argumentos no es un problema.
Esto puede ser lento debido a que tiene que procesar cada archivo individualmente. Usar xargs podría proporcionar una solución más eficiente:
xargs puede tomar la lista completa de archivos provista por find y dividirla en listas de argumentos de tamaños manejables y ejecutar cp en cada una de esas sublistas.
Por supuesto, también existe la posibilidad de recompilar su kernel, estableciendo un valor mayor para
MAX_ARG_PAGES
. Pero recompilar un kernel es más trabajo del que estoy dispuesto a explicar en esta respuesta.fuente
xargs
parece ser mucho más eficiente, ya que el número resultante de llamadas de comando es mucho menor. En mi caso, veo un rendimiento entre 6 y 12 veces mejor cuando lo uso,args
y cuando uso una-exec
solución con un número creciente de archivos aumenta la eficiencia.Eso sucede porque su expresión comodín (
*.jpg
) excede el límite de longitud del argumento de la línea de comando cuando se expande (probablemente porque tiene muchos archivos .jpg debajo/home/ftpuser/public_html/ftparea
).Hay varias formas de sortear esa limitación, como usar
find
oxargs
. Eche un vistazo a este artículo para obtener más detalles sobre cómo hacerlo.fuente
Como comentó GoldPseudo, hay un límite en la cantidad de argumentos que puede pasar a un proceso que está generando. Vea su respuesta para una buena descripción de ese parámetro.
Puede evitar el problema al no pasar demasiados argumentos al proceso o al reducir el número de argumentos que pasa.
Un bucle for en el shell, find, y ls, grep y un bucle while hacen lo mismo en esta situación:
y
y
todos tienen un programa que lee el directorio (el propio shell, find y ls) y un programa diferente que realmente toma un argumento por ejecución e itera a través de la lista completa de comandos.
Ahora, esto será lento porque la rm debe bifurcarse y ejecutarse para cada archivo que coincida con el patrón * .jpg.
Aquí es donde entra en juego xargs. xargs toma la entrada estándar y por cada N (para freebsd es por defecto 5000) líneas, genera un programa con N argumentos. xargs es una optimización de los bucles anteriores porque solo necesita bifurcar programas 1 / N para iterar sobre todo el conjunto de archivos que leen argumentos desde la línea de comandos.
fuente
Hay un número máximo de argumentos que se pueden especificar a un programa, bash expande * .jpg a muchos argumentos para cp. Puede resolverlo utilizando find, xargs o rsync, etc.
Echa un vistazo aquí sobre xargs y encuentra
/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names
fuente
El globo '*' se está expandiendo a demasiados nombres de archivo. Use find / home / ftpuser / public_html -name '* .jpg' en su lugar.
fuente
Usar la
+
opción parafind -exec
acelerará enormemente la operación.La
+
opción requiere{}
ser el último argumento, por lo que usar la opción-t /your/destination
(o--target-directory=/your/destination
) paracp
que funcione.De
man find
:Editar : argumentos reorganizados para cp
fuente
cp
para corregir ese error.Parece que tiene demasiados
*.jpg
archivos en ese directorio para ponerlos a todos en la línea de comando a la vez. Tu podrías intentar:Es posible que deba verificar
man xargs
su implementación para ver si el-I
conmutador es correcto para su sistema.En realidad, ¿realmente tiene la intención de copiar esos archivos en la misma ubicación donde ya están?
fuente
ls
tendrá el mismo problema! He cambiado afind
lo que no.Ir a la carpeta
y ejecuta lo siguiente:
De esta manera, si la carpeta 'ftparea' tiene subcarpetas, esto podría ser un efecto negativo si solo desea los archivos '* .jpg', pero si no hay ninguna subcarpeta, este enfoque será definitivamente mucho más rápido que usando find y xargs
fuente