xargs
espera um formato de entrada muito especial em que os argumentos sejam delimitados por espaços em branco ou novas linhas (às vezes outras formas de espaço em branco vertical, às vezes dependentes da localidade atual) e onde aspas simples, aspas duplas e barra invertida podem ser usadas para evitá-las (mas de uma maneira diferente caminho de aspas shell).
-l1
não é passar uma linha de entrada como um único argumento para mkdir
, mas chamar uma mkdir
chamada para cada linha de entrada, mas com palavras nessa linha ainda separadas por argumentos diferentes para mkdir
.
A implementação do GNU xargs
adicionou uma -0
opção décadas atrás para aceitar dados delimitados por NUL. Essa é a maneira mais óbvia de separar palavras que acabarão sendo argumentos para um comando, porque o caractere NUL passa a ser o único caractere que não pode ocorrer em um argumento de comando ou nome de arquivo (o formato de lista escolhido que coloca um arquivo por linha não pode representar todos os nomes de arquivos possíveis, pois não permite uma nova linha em um nome de arquivo).
Isso -0
foi copiado por várias outras xargs
implementações, mas não por todas.
Com aqueles que você pode fazer:
<file tr '\n' '\0' | xargs -0 mkdir -p --
Isso chamará o menor mkdir
número de vezes possível com o maior número de argumentos possível.
Mas observe que, se file
estiver vazio, mkdir
ainda será executado e você receberá um erro de sintaxe mkdir
devido ao argumento ausente. O GNU xargs
adicionou uma -r
opção para o que foi copiado por algumas outras implementações.
O GNU xargs
também adicionou (mais tarde) uma -d
opção para poder especificar delimitadores arbitrários, mas acho que nenhuma outra implementação o copiou. Com o GNU xargs
, a melhor maneira é:
xargs -rd '\n' -a file mkdir -p --
Ao passar o arquivo com -a
(também uma extensão GNU) em vez de stdin, isso significa que mkdir
o stdin é preservado.
POSIX, você precisaria pós-processar a entrada para colocá-la no formato esperado por xargs
. Você poderia fazê-lo, por exemplo, com:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --
Onde colocar cada linha dentro de aspas e escapar cada "
como "\""
antes de alimentar a xargs.
Mas cuidado com as possíveis limitações:
- o erro quando o arquivo está vazio já mencionado acima
- pode falhar em algumas implementações (inclusive de
sed
) se o conteúdo de file
não for um texto válido no código do idioma atual. Se file
contiver nomes de arquivos codificados em mais de um conjunto de caracteres diferente, ou um conjunto de caracteres diferente daquele do código de idioma, será possível corrigir o código de idioma em C, o que deve ajudar.
- algumas
xargs
implementações têm limites ridiculamente baixos no tamanho máximo de um argumento (pode ser tão baixo quanto 255 bytes).
Para contornar o erro de sintaxe após um erro de entrada vazio , você pode escrever:
<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh
-d
opção.