Eu estou perdendo duas twings nas respostas aqui, então estou adicionando mais uma.
Embora isso me lembre de adicionar outra resposta standard ...
Existemdoisproblemasaqui:
Ihaveadirectorycontainingaround280,000files.
Amaioriadasferramentasnãoseadaptatãobemaessenúmerodearquivos.NãoapenasamaioriadasferramentasdoLinuxouferramentasdoWindows,masmuitosprogramas.Eissopodeincluirseusistemadearquivos.Asoluçãoalongoprazoseria"bem, não faça isso então". Se você tiver arquivos diferentes, mas eles em diretórios diferentes. Se não espera continuar encontrando problemas no futuro.
Dito isso, vamos ao seu problema real:
If I use cp or mv then I get an error 'argument list too long'
Isso é causado pela expansão de * pelo shell. O shell tem espaço limitado para o resultado e ele se esgota. Isso significa que qualquer comando com um *
expandido pelo shell terá o mesmo problema. Você precisará expandir menos opções ao mesmo tempo ou usar um comando diferente.
Um comando alternativo usado com frequência quando você se depara com esse problema é find
. Já existem várias respostas mostrando como usá-lo, então não vou repetir tudo isso. No entanto, vou salientar a diferença entre \;
e +
, pois isso pode fazer uma grande diferença de desempenho e se encaixar perfeitamente na explicação de expansão anterior.
find /path/to/search --name "*.txt" -exec command {} \;
Encontrará todos os arquivos em path / to / search / e executará um comando com ele, mas observe as aspas em torno do *
. Isso alimenta o * para o comando. Se nós não o encapsulássemos ou escaparmos, o shell tentaria expandi-lo e obteríamos o mesmo erro.
Por fim, quero mencionar algo sobre {}. Esses colchetes são substituídos pelo conteúdo encontrado por find. Se você terminar o comando com um ponto-e-vírgula ;
(um que você precisa escapar do shell, portanto, \;
nos exemplos), os resultados serão passados um por um. Isso significa que você executará 280000 comandos mv. Um para cada arquivo. Isso pode ser lento.
Como alternativa, você pode terminar com +
. Isso passará tantos argumentos quanto possível ao mesmo tempo. Se o bash puder manipular 2000 argumentos, então, find / path -name "* filetype" -exec some_move {} + chamará o comando some_move cerca de 140 vezes, cada vez com 2000 argumentos. Isso é mais eficiente (leia: mais rápido).