Estou usando o seguinte comando:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
E estou recebendo o erro:
-bash: /bin/cp: Argument list too long
Eu também tentei:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
Ainda tem -bash: / bin / ls: lista de argumentos muito longa
Alguma ideia?
linux
bash
unix-shell
icelizard
fonte
fonte
ls
não foi projetado para fazer esse tipo de coisa. Usefind
.ls
foi especialmente projetado para fazer isso: mywiki.wooledge.org/ParsingLsRespostas:
* .jpg se expande para uma lista maior do que o shell pode suportar. Tente isso em vez disso
fonte
Há um limite máximo para quanto tempo uma lista de argumentos pode ter para comandos do sistema - esse limite é específico da distribuição com base no valor de
MAX_ARG_PAGES
quando o kernel é compilado e não pode ser alterado sem recompilar o kernel.Devido à maneira como o globbing é tratado pelo shell, isso afetará a maioria dos comandos do sistema quando você usar o mesmo argumento ("* .jpg"). Como o glob é processado pelo shell primeiro e depois enviado ao comando, o comando:
é essencialmente o mesmo para o shell, como se você tivesse escrito:
Se você está lidando com muitos jpegs, isso pode se tornar incontrolável muito rapidamente. Dependendo da sua convenção de nomenclatura e do número de arquivos que você realmente precisa processar, é possível executar o comando cp em um subconjunto diferente do diretório por vez:
Isso poderia funcionar, mas exatamente o quão eficaz seria se baseia em quão bem você pode dividir sua lista de arquivos em blocos convenientes.
Globbable. Eu gosto dessa palavra.
Alguns comandos, como o find e o xargs , podem lidar com grandes listas de arquivos sem criar listas de argumentos de tamanho reduzido.
O argumento -exec executará o restante da linha de comando uma vez para cada arquivo encontrado por find , substituindo o {} por cada nome de arquivo encontrado. Como o comando cp é executado apenas em um arquivo por vez, o limite da lista de argumentos não é um problema.
Isso pode ser lento devido à necessidade de processar cada arquivo individualmente. Usar xargs poderia fornecer uma solução mais eficiente:
O xargs pode pegar a lista completa de arquivos fornecida pelo find e dividi-la em listas de argumentos de tamanhos gerenciáveis e executar cp em cada uma dessas sublistas.
Obviamente, também há a possibilidade de recompilar seu kernel, configurando um valor maior para
MAX_ARG_PAGES
. Mas recompilar um kernel é mais trabalhoso do que estou disposto a explicar nesta resposta.fonte
xargs
parece ser muito mais eficiente, pois o número resultante de chamadas de comando é muito menor. No meu caso, eu vejo desempenho de 6 a 12 vezes melhorargs
ao usar a-exec
solução com um número crescente de arquivos, aumentando a eficiência.Isso acontece porque sua expressão curinga (
*.jpg
) excede o limite de tamanho do argumento da linha de comando quando expandida (provavelmente porque você tem muitos arquivos .jpg abaixo/home/ftpuser/public_html/ftparea
).Existem várias maneiras de contornar essa limitação, como usar
find
orxargs
. Dê uma olhada neste artigo para obter mais detalhes sobre como fazer isso.fonte
Como GoldPseudo comentou, há um limite para quantos argumentos você pode passar para um processo que está gerando. Veja a resposta dele para uma boa descrição desse parâmetro.
Você pode evitar o problema não passando muitos argumentos no processo ou reduzindo o número de argumentos que está passando.
Um loop for no shell, find e ls, grep e um loop while fazem a mesma coisa nessa situação -
e
e
todos têm um programa que lê o diretório (o próprio shell, localize e sl) e um programa diferente que, na verdade, recebe um argumento por execução e itera por toda a lista de comandos.
Agora, isso será lento porque a rm precisa ser bifurcada e executada para cada arquivo que corresponda ao padrão * .jpg.
É aqui que o xargs entra em jogo. O xargs recebe entrada padrão e para cada N (para freebsd é por padrão 5000) linhas, gera um programa com N argumentos. xargs é uma otimização dos loops acima, porque você só precisa bifurcar programas 1 / N para iterar todo o conjunto de arquivos que lêem argumentos na linha de comando.
fonte
Há um número máximo de argumentos que podem ser especificados para um programa, o bash expande * .jpg para muitos argumentos para cp. Você pode resolvê-lo usando find, xargs ou rsync etc.
Dê uma olhada aqui sobre xargs e encontre
/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names
fonte
A glob '*' está se expandindo para muitos nomes de arquivos. Use find / home / ftpuser / public_html -name '* .jpg'.
fonte
Usar a
+
opção parafind -exec
acelerará bastante a operação.A
+
opção precisa{}
ser o último argumento, portanto, use a opção-t /your/destination
(ou--target-directory=/your/destination
) paracp
fazê-lo funcionar.De
man find
:Editar : argumentos reorganizados para cp
fonte
cp
para corrigir esse erro.Parece que você tem muitos
*.jpg
arquivos nesse diretório para colocá-los todos na linha de comando de uma só vez. Você poderia tentar:Pode ser necessário verificar
man xargs
sua implementação para ver se a-I
opção está correta para o seu sistema.Na verdade, você realmente pretende copiar esses arquivos para o mesmo local em que eles já estão?
fonte
ls
que terá o mesmo problema! Eu mudei para ofind
que não.Vá para a pasta
e execute o seguinte:
Dessa forma, se a pasta 'ftparea' tiver subpastas, isso poderá ser um efeito negativo se você quiser apenas os arquivos '* .jpg', mas se não houver subpastas, essa abordagem será definitivamente muito mais rápida do que usando find e xargs
fonte