O que esta solução zsh para “a lista de argumentos é muito longa” faz?

6

Eu li em esta resposta de @Gilles o seguinte:

In zsh, you can load the mv builtin:

setopt extended_glob
zmodload -Fm zsh/files b:zf_\*
mv -- ^*.(jpg|png|bmp) targetdir/

como uma solução para o problema "mv: Argument list too long” . A resposta sugere o uso do mv do zsh (em oposição ao GNU), mas o que exatamente essa linha faz?:

zmodload -Fm zsh/files b:zf_\*
    
por Amelio Vazquez-Reina 17.09.2014 / 21:55

2 respostas

11

A melhor maneira de ver a documentação do zsh é usando info .

Se você executar info zsh , você pode usar o índice (pense em um índice do livro ) para localizar a seção que descreve o comando zmodload .

Pressione i , então você pode inserir zmo e pressionar a tecla Tab . Você vai direto para a descrição de zmodload que lhe contará tudo sobre isso.

Em suma, zmodload -F carrega o módulo (se não carregado) e ativa somente os recursos especificados desse módulo.

Com -m , ativamos os recursos que m atingem um padrão, aqui b:zf_* . b: é para builtin, portanto, o comando acima carrega o módulo zsh/files (consulte info -f zsh -n 'The zsh/files Module,' para obter detalhes sobre isso) e ativa somente os construtores cujo nome começa com zf_ .

zmodload -F zsh/files

carrega o módulo, mas não ativa nenhum recurso:

$ zmodload -FlL zsh/files
zmodload -F zsh/files -b:chgrp -b:chown -b:ln -b:mkdir -b:mv -b:rm -b:rmdir -b:sync -b:zf_chgrp -b:zf_chown -b:zf_ln -b:zf_mkdir -b:zf_mv -b:zf_rm -b:zf_rmdir -b:zf_sync

lista os recursos desse módulo especificando quais estão atualmente ativados (nenhum por enquanto). Você notará que há um mv e zf_mv incorporado.

$ zmodload -mF zsh/files 'b:zf_*'
$ zmodload -FlL zsh/files
zmodload -F zsh/files -b:chgrp -b:chown -b:ln -b:mkdir -b:mv -b:rm -b:rmdir -b:sync +b:zf_chgrp +b:zf_chown +b:zf_ln +b:zf_mkdir +b:zf_mv +b:zf_rm +b:zf_rmdir +b:zf_sync

Você notará que o zf_mv builtin foi ativado, mas não o mv one (o mesmo para os outros arquivos incorporados). Isso significa que as versões embutidas dos comandos do sistema foram ativadas, mas sem substituir o sistema:

$ type zf_mv
zf_mv is a shell builtin
$ type mv
mv is /bin/mv

Agora que você tem um mv embutido, como zf_mv , não mv , você pode fazer:

zf_mv -- ^*.(jpg|png|bmp) targetdir/

Como zf_mv está embutido, não há nenhuma chamada de sistema execve() , portanto você não atingirá o limite Too many args associado a ele.

Claro, você também pode fazer:

zmodload zsh/files # without -F, all the features are enabled
mv -- ^*.(jpg|png|bmp) targetdir/

Mas cuidado, pois isso substitui o mv do sistema por zsh do equivalente incorporado.

Para superar o erro E2BIG execve() (o Too many args ao executar um comando externo), zsh também fornece uma função zargs .

Você executa:

autoload zargs # in ~/.zshrc if you use it often

Para marcá-lo para o carregamento automático.

Então você pode usar:

zargs -- ^*.(jpg|png|bmp) -- mv -t targetdir/

(assumindo aqui o GNU mv para a opção -t ). zargs executará quantos comandos mv forem necessários para evitar o E2BIG (como xargs faria).

    
por 17.09.2014 / 22:57
-2

Existe uma solução universal que não depende do basismo: xargs .

xargs lê um fluxo de argumentos de stdin e os transmite para o utilitário especificado arbitrariamente. No seu caso, é assim que a linha de comando deve ser:

# find -E /source/dir -iregex ".*\.(jpg|png|bmp)" | xargz -n 1 -J % mv % /target/dir

Aqui -E significa que find usou os regexes modernos (para | alternativas), -n 1 significa que o fluxo de entrada será dividido em argumentos únicos, -J % significa que cada argumento será substituído na próxima ocorrência do % char.

-J % é necessário porque xargs acrescenta um argumento ao final do comando filho por padrão. Ausência de -J % é equivalente ao xargs -n 1 -J % mv /target/dir % que definitivamente não é o que você quer.

    
por 17.09.2014 / 22:53

Tags