$ ls *mp3 | xargs mplayer
Playing Lemon.
File not found: 'Lemon'
Playing Tree.mp3.
File not found: 'Tree.mp3'
Exiting... (End of file)
Meu comando falha porque o arquivo "Lemon Tree.mp3" contém espaços e, portanto, o xargs pensa que são dois arquivos. Posso fazer o find + xargs funcionar com nomes de arquivos como este?
ls |grep mp3 |sed -n "7p"
você pode apenas usarecho "Lemon Tree.mp3"
.Respostas:
O
xargs
comando usa caracteres de espaço em branco (tabulações, espaços, novas linhas) como delimitadores. Você pode reduzi-lo apenas para os novos caracteres de linha ('\ n') com a-d
opção como esta:Funciona apenas com GNU xargs. Para sistemas BSD, use a
-0
opção como esta:Este método é mais simples e funciona com o GNU xargs também.
fonte
-E
, ex:xargs -E '\n'
O utilitário xargs lê cadeias delimitadas por espaço, tabulação, nova linha e fim de arquivo a partir da entrada padrão e executa o utilitário com as cadeias como argumentos.
Você deseja evitar o uso do espaço como delimitador. Isso pode ser feito alterando o delimitador para xargs. De acordo com o manual:
Tal como:
Para responder à pergunta sobre tocar o sétimo mp3; é mais simples de executar
fonte
find
e GNUxargs
; nem todas as versões desses programas suportam essas opções (embora exista um argumento a ser feito).find
com-print0
exargs
com-0
. No entanto, AFAIK, HP-UX, AIX e Solaris não o fazem (mas devo ser corrigido: o HP-UX 11i não; Solaris 10 não; AIX 5.x não; mas não são as versões atuais ) Não seria difícil mudarsed
, por exemplo, usar 'linhas' terminando com e'\0'
não'\n'
, e o POSIX 2008getdelim()
facilitaria o gerenciamento.Experimentar
ao invés de
fonte
O xargs no MacOS não possui a opção -d, portanto, esta solução usa -0.
Obtenha ls para gerar um arquivo por linha, depois converta novas linhas em nulos e diga ao xargs para usar nulos como delimitador:
ls -1 *mp3 | tr "\n" "\0" | xargs -0 mplayer
fonte
Isso ajudou no meu caso a excluir arquivos diferentes com espaços. Deve funcionar também com o mplayer. O truque necessário são as aspas. (Testado no Linux Xubuntu 14.04.)
fonte
A resposta de Dick.Guertin [1] sugeriu que alguém poderia escapar dos espaços em um nome de arquivo é uma alternativa valiosa para outras soluções sugeridas aqui (como usar um caractere nulo como separador em vez de espaço em branco). Mas poderia ser mais simples - você realmente não precisa de um personagem único. Você pode simplesmente adicionar os espaços escapados diretamente:
Além disso, o grep é necessário apenas se você quiser apenas arquivos com espaços nos nomes. Mais genericamente (por exemplo, ao processar um lote de arquivos, alguns dos quais têm espaços, outros não), basta pular o grep:
Então, é claro, o nome do arquivo pode ter outro espaço em branco além de espaços em branco (por exemplo, uma guia):
Isso pressupõe que você tenha um sed que suporte -r (regex estendido), como GNU sed ou versões recentes do bsd sed (por exemplo, FreeBSD que originalmente soletrou a opção "-E" antes do FreeBSD 8 e suporta -r & -E para compatibilidade pelo FreeBSD 11, pelo menos). Caso contrário, você pode usar uma expressão básica de colchete de classe de caracteres regex e inserir manualmente os caracteres de espaço e tabulação nos
[]
delimitadores.[1] Talvez seja mais apropriado como comentário ou edição para essa resposta, mas no momento não tenho reputação suficiente para comentar e só posso sugerir edições. Como as últimas formas acima (sem o grep) alteram o comportamento da resposta original de Dick.Guertin, uma edição direta talvez não seja apropriada.
fonte
ls | grep mp3 | sed -n "7p" | xargs -i mplayer {}
Observe que no comando acima,
xargs
será chamadomplayer
novamente para cada arquivo. Isso pode ser indesejávelmplayer
, mas pode ser bom para outros destinos.fonte
mplayer
que seja chamado novamente para cada arquivo. É importante se você tentar, por exemplo... | xargs -I{} mplayer -shuffle {}
: apesar de tudo, isso será executado em uma ordem completamente determinística-shuffle
.xargs
é usado principalmente com comandos que aceitam uma lista de nomes de arquivos (exemplo fácil:)rm
e tenta passar quantos nomes de arquivos puderem caber em cada invocação, dividindo-os em várias invocações, se necessário. Você pode ver a diferença ao usar um comando em que cada chamada é visível, comoecho
(o padrão):seq 0 100000 | xargs
imprime todos os números de 0 a 23695 (específico da plataforma, mas é o que acontece no meu sistema) na primeira linha, para 45539 na linha 2, etc. E você está certo, para a maioria dos comandos, isso não importa.No macOS 10.12.x (Sierra), se você tiver espaços em nomes ou subdiretórios de arquivos, poderá usar o seguinte:
fonte
Depende de (a) quão apegado você está ao número 7, em vez de, digamos, limões, e (b) se algum dos seus nomes de arquivo contém novas linhas (e se você deseja renomeá-lo, se houver).
Há muitas maneiras de lidar com isso, mas algumas são:
O
read
loop não funciona se os nomes dos arquivos contiverem novas linhas; os outros funcionam corretamente mesmo com novas linhas nos nomes (sem falar em espaços). Pelo meu dinheiro, se você tiver nomes de arquivos contendo uma nova linha, renomeie o arquivo sem a nova linha. Usar aspas duplas ao redor do nome do arquivo é a chave para que os loops funcionem corretamente.Se você possui GNU
find
e GNUxargs
(ou FreeBSD (* BSD?) Ou Mac OS X), também pode usar as opções-print0
e-0
, como em:Isso funciona independentemente do conteúdo do nome (os dois únicos caracteres que não podem aparecer em um nome de arquivo são barra e NUL, e a barra não causa problemas no caminho do arquivo, portanto, usar NUL como o delimitador de nome cobre tudo). No entanto, se você precisar filtrar as 6 primeiras entradas, precisará de um programa que lide com 'linhas' terminadas por NUL em vez de nova linha ... e não tenho certeza de que haja alguma.
O primeiro é de longe o mais simples para o caso específico em questão; no entanto, pode não ser generalizado para cobrir seus outros cenários que você ainda não listou.
fonte
Sei que não estou respondendo
xargs
diretamente à pergunta, mas vale a pena mencionarfind
a-exec
opção.Dado o seguinte sistema de arquivos:
O comando find pode ser feito para lidar com o espaço no Dream Theater e no King's X. Portanto, para encontrar os bateristas de cada banda usando grep:
No
-exec
opção,{}
está o nome do arquivo, incluindo o caminho. Observe que você não precisa escapá-lo ou colocá-lo entre aspas.A diferença entre
-exec
os terminadores (+
e\;
) é que+
agrupa quantos nomes de arquivos puderem em uma linha de comando. Considerando que\;
irá executar o comando para cada nome de arquivo.Assim,
find bands/ -type f -exec grep Drums {} +
resultará em:e
find bands/ -type f -exec grep Drums {} \;
resultará em:No caso de
grep
tem o efeito colateral de imprimir ou não o nome do arquivo.Obviamente,
grep
as opções de-h
e-H
controlarão se o nome do arquivo é ou não impresso, independentemente de comogrep
é chamado.xargs
xargs
também pode controlar como os arquivos man estão na linha de comando.xargs
por padrão, agrupa todos os argumentos em uma linha. Para fazer a mesma coisa que-exec \;
usaxargs -l
. Observe que a-t
opção informaxargs
para imprimir o comando antes de executá-lo.Veja que o
-l
opção diz ao xargs para executar grep para cada nome de arquivo.Versus o padrão (ou seja, nenhuma
-l
opção):xargs
tem melhor controle sobre quantos arquivos podem estar na linha de comando. Dê à-l
opção o número máximo de arquivos por comando.Veja que
grep
foi executado com dois nomes de arquivos por causa de-l2
.fonte
Dado o título específico deste post, aqui está minha sugestão:
A idéia é converter espaços em branco em qualquer caractere exclusivo, como '<', e depois alterá-lo para '\', uma barra invertida seguida por um espaço em branco. Você pode canalizar isso para qualquer comando que desejar, como:
A chave aqui está nos comandos 'tr' e 'sed'; e você pode usar qualquer caractere além de '<', como '?' ou mesmo um caractere de tabulação.
fonte
tr
? Por que não apenasls *.mp3 | sed -n '7!b;s/\([[:space:]]\)/\\\1/g;p'
?Soluções alternativas podem ser úteis ...
Você também pode adicionar um caractere nulo ao final de suas linhas usando Perl e, em seguida, usar a
-0
opção em xargs. Diferente do xargs -d '\ n' (na resposta aprovada) - isso funciona em qualquer lugar, incluindo o OS X.Por exemplo, para listar recursivamente (executar, mover etc.) arquivos MPEG3 que podem conter espaços ou outros caracteres engraçados - eu usaria:
(Nota: para filtrar, prefiro a sintaxe "| grep" mais fácil de lembrar do que os argumentos "find's" --name.)
fonte