Como posso fazer xargs executar o comando exatamente uma vez para cada linha de entrada fornecida? Seu comportamento padrão é dividir as linhas e executar o comando uma vez, passando várias linhas para cada instância.
De http://en.wikipedia.org/wiki/Xargs :
encontrar / caminho-tipo f -print0 | xargs -0 rm
Neste exemplo, find alimenta a entrada de xargs com uma longa lista de nomes de arquivos. O xargs divide essa lista em sublistas e chama rm uma vez para cada sublist. Isso é mais eficiente que esta versão funcionalmente equivalente:
encontre / caminho -type f -exec rm '{}' \;
Eu sei que esse achado tem a bandeira "exec". Estou apenas citando um exemplo ilustrativo de outro recurso.
find /path -type f -delete
seria ainda mais eficiente :)Respostas:
O seguinte funcionará apenas se você não tiver espaços em sua entrada:
na página do manual:
fonte
xargs -n 1
o que você deu mostrou "lista de argumentos muito longa".MAX-LINES
for omitido, o padrão será 1, portanto,xargs -l
é suficiente. Vejainfo xargs
.echo "foo bar" | xargs -n1 echo
. portanto, se você digitar coisas como 'ls', ele não lidará bem com espaços.-L 1
não responde à pergunta original e o-n 1
faz apenas em uma das possíveis interpretações. Veja minha longa resposta abaixo.-L 1
faz. Para mim, o OP parecia estar claramente tentando evitar o comportamento padrão de fragmentação e, como isso foi aceito, presumo que estava certo. Sua resposta aborda um caso de uso ligeiramente diferente, no qual você também deseja o comportamento de chunking.Parece-me que todas as respostas existentes nesta página estão incorretas, incluindo a marcada como correta. Isso decorre do fato de que a pergunta é ambígua.
Resumo: Se você deseja executar o comando "exatamente uma vez para cada linha de entrada fornecida", passando a linha inteira (sem a nova linha) para o comando como um único argumento, esta é a melhor maneira compatível com UNIX:
O GNU
xargs
pode ou não ter extensões úteis que permitem eliminartr
, mas elas não estão disponíveis no OS X e em outros sistemas UNIX.Agora, para a longa explicação…
Há dois problemas a serem considerados ao usar o xargs:
Para testar o comportamento do xargs, precisamos de um utilitário que mostre quantas vezes ele está sendo executado e com quantos argumentos. Não sei se existe um utilitário padrão para fazer isso, mas podemos codificá-lo facilmente no bash:
Supondo que você o salve como
show
em seu diretório atual e o torne executável, veja como funciona:Agora, se a pergunta original é realmente sobre o ponto 2. acima (como eu acho que é, depois de ler algumas vezes) e deve ser lida assim (alterações em negrito):
então a resposta é
-n 1
.Vamos comparar o comportamento padrão do xargs, que divide a entrada em branco e chama o comando o menor número de vezes possível:
e seu comportamento com
-n 1
:Se, por outro lado, a pergunta original era sobre a divisão de entradas do ponto 1. e era para ser lida assim (muitas pessoas que vêm aqui parecem pensar que é esse o caso, ou estão confundindo as duas questões):
então a resposta é mais sutil.
Alguém poderia pensar que isso
-L 1
poderia ajudar, mas acontece que não muda a análise de argumentos. Ele executa o comando apenas uma vez para cada linha de entrada, com tantos argumentos quanto nessa linha de entrada:Não apenas isso, mas se uma linha termina com espaço em branco, ela é anexada à seguinte:
Claramente,
-L
não se trata de mudar a maneira como o xargs divide a entrada em argumentos.O único argumento que faz isso de uma forma multiplataforma (excluindo extensões GNU) é
-0
, que divide a entrada em torno de bytes NUL.Depois, basta traduzir novas linhas para NUL com a ajuda de
tr
:Agora, a análise do argumento parece correta, incluindo o espaço em branco à direita.
Por fim, se você combinar essa técnica
-n 1
, obterá exatamente uma execução de comando por linha de entrada, qualquer que seja sua entrada, que pode ser outra maneira de analisar a questão original (possivelmente a mais intuitiva, considerando o título):fonte
-L
executa o comando uma vez por linha de entrada (mas um espaço no final de uma linha o une à próxima linha, e a linha ainda é dividida em argumentos de acordo com o espaço em branco); enquanto-n
executa o comando uma vez por argumento de entrada. Se você contar o número de->
nos exemplos de saída, esse é o número de vezes que o script./show
é executado.xargs
pode ou não ter extensões úteis que permitem acabar comtr
ele. Tem uma extensão muito útil; fromxargs --help
- -d, --delimiter = Os itens CHARACTER no fluxo de entrada são separados por CHARACTER, não por espaço em branco; desativa citar e processamento de barra invertida e processamento EOF lógica-L
.-L
não diz quantas vezes executar o script por linha, diz quantas linhas de dados de entrada devem consumir por vez.Se você deseja executar o comando para cada linha (ou seja, resultado) proveniente
find
, para que precisaxargs
?Tentar:
find
caminho-type f -exec
seu comando{} \;
onde o literal
{}
é substituído pelo nome do arquivo e o literal\;
é necessário parafind
saber que o comando personalizado termina aí.EDITAR:
(após a edição da sua pergunta, esclarecendo que você conhece
-exec
)De
man xargs
:Observe que os nomes de arquivos que terminam em espaços em branco podem causar problemas se você usar
xargs
:Portanto, se você não se importa com a
-exec
opção, é melhor usar-print0
e-0
:fonte
-L 1
é a solução simples, mas não funciona se algum dos arquivos contiver espaços. Esta é uma função essencial do-print0
argumento de localização - para separar os argumentos pelo caractere '\ 0' em vez de espaço em branco. Aqui está um exemplo:Uma solução melhor é usar
tr
para converter novas linhas em\0
caracteres nulos ( ) e, em seguida, use oxargs -0
argumento Aqui está um exemplo:Se você precisar limitar o número de chamadas, poderá usar o
-n 1
argumento para fazer uma chamada ao programa para cada entrada:Isso também permite filtrar a saída de localização antes de converter as quebras em nulos.
fonte
-L
também é que ele não permite vários argumentos para cadaxargs
chamada de comando".Outra alternativa ...
fonte
Essas duas maneiras também funcionam e funcionarão para outros comandos que não estão usando o find!
exemplo de caso de uso:
excluirá todos os arquivos pyc nesse diretório, mesmo que os arquivos pyc contenham espaços.
fonte
é tudo o que você precisa.
fonte
O comando a seguir encontrará todos os arquivos (-tipo f)
/path
e os copiarácp
para a pasta atual. Observe o uso if-I %
para especificar um caractere de espaço reservado nacp
linha de comando para que os argumentos possam ser colocados após o nome do arquivo.find /path -type f -print0 | xargs -0 -I % cp % .
Testado com xargs (GNU findutils) 4.4.0
fonte
Você pode limitar o número de linhas ou argumentos (se houver espaços entre cada argumento) usando os sinalizadores --max-lines ou --max-args, respectivamente.
fonte
Parece que não tenho reputação suficiente para adicionar um comentário à resposta de Tobia acima , então estou adicionando essa "resposta" para ajudar aqueles que desejam experimentar
xargs
da mesma maneira nas plataformas Windows.Aqui está um arquivo em lotes do Windows que faz a mesma coisa que o script "show" rapidamente codificado por Tobia:
fonte
As respostas do @Demonemon parecem estar corretas com "-0", mesmo com espaço no arquivo.
Eu estava tentando o comando xargs e descobri que "-0" funciona perfeitamente com "-L". até os espaços são tratados (se a entrada foi nula finalizada). o seguinte é um exemplo:
A seguir, os valores nulos serão divididos e o comando será executado em cada argumento da lista:
portanto
-L1
, executará o argumento em cada caractere terminado nulo se usado com "-0". Para ver a diferença, tente:mesmo isso será executado uma vez:
O comando será executado uma vez, pois o "-L" agora não é dividido em byte nulo. você precisa fornecer "-0" e "-L" para funcionar.
fonte
No seu exemplo, o ponto de canalizar a saída de find para xargs é que o comportamento padrão da opção -exec de find é executar o comando uma vez para cada arquivo encontrado. Se você estiver usando find e quiser o comportamento padrão, a resposta é simples - não use xargs para começar.
fonte
find
, e é por isso que eles não preferem a-exec
opção.execute a tarefa ant limpar tudo em todos os build.xml da atual ou subpasta.
fonte
ant
instalou.