'xargs' com espaços em nomes de arquivos

7

Estou tentando listar apenas arquivos sem imagem , pesquisando apenas nos 500 arquivos mais recentes. Então eu corro

ls -t | head -500 | file | grep -v 'image'

que não está certo: exibe uma mensagem de ajuda. Alterando para

ls -t | head -500 | xargs file | grep -v 'image'

Agora, às vezes recebo a saída desejada, mas se o nome do arquivo tiver espaços - por exemplo, Plutonian\ Nights\ -\ Sun\ Ra.mp3 -, então xargs será executado file Plutonian , file Nights , etc.

Como posso ajudar xargs a ver os espaços ou realizar o que estou tentando realizar?

    
por isomorphismes 01.05.2015 / 16:10

5 respostas

5

Usando xargs , isso pode ser feito da seguinte maneira:

find . -type f -print0 | xargs -0 file | grep -v 'image' 

Mas xargs é tão ontem. As crianças legais usam parallel hoje. Usando paralela, seria:

find . -type f | parallel file | grep -v 'image'

Veja. Não use -print0 e -0. parallel é realmente inteligente por si só.

ATUALIZAÇÃO

Para listar somente os 500 arquivos mais recentes, seu comando seria:

ls -1t | head -500 | parallel file {} | grep -v image

Importante

Caso o seu paralelo seja antigo e a sintaxe acima não funcione, instale a nova versão do paralelo, conforme explicado aqui: link

    
por 04.05.2015 / 11:40
2

Use "encontrar" com a opção "-print0" & canalize a saída para "xargs" com a opção "-0".

Embora eu saiba (e use) essa técnica, vejo que o usuário @Jens respondeu a uma pergunta semelhante, na qual você pode encontrar mais detalhes:

link

    
por 01.05.2015 / 16:36
1

Eu tenho duas sugestões cruas que podem ajudar. No entanto, nenhum dos dois se sente particularmente satisfatório, então talvez algo melhor apareça.

Primeiro, use o sed para adicionar aspas a tudo, para que você só tenha problemas se houver citações no nome do arquivo, como

ls -t | head -500 | sed -e 's/\(.*\)/""/' | xargs file | grep -v 'image'

O outro é usar o ls para encontrar o 501º mais recente, então use o find para obter o material mais novo como

find -newer $(ls -t | head -501 | tail -1) -type f -exec file {} \; | grep -v image
    
por 01.05.2015 / 16:23
1

Para obter conselhos genéricos sobre o processamento de nomes de arquivos potencialmente contendo espaços, consulte Por que meu script de shell sufoca em espaços em branco ou outros caracteres especiais?

A dificuldade com o que você está tentando fazer é que não há uma boa maneira de listar os N arquivos mais recentes com ferramentas padrão.

A maneira mais fácil de fazer o que você está fazendo aqui é usar zsh como seu shell. Ele tem qualificadores para classificar arquivos por data. Para executar file nos 500 arquivos mais recentes:

file *(om[1,500])

Com o utilitário file do Linux, passe a opção -i ou --mime-type para obter uma saída mais fácil de analisar. Os arquivos de imagem são identificados por linhas que terminam com image/something .

file --mime-type *(om[1,500]) | sed -n 's~: *image/[^ ]*$~~p'

Se você precisar lidar com absolutamente todos os nomes de arquivos, incluindo aqueles com uma nova linha em seus nomes, use a opção -0 para saída delimitada por nulo. Versões recentes do GNU sed podem usar bytes nulos como o delimitador de registro em vez de novas linhas.

file --mime-type -- *(om[1,500]) | sed -zn 's~: *image/[^ ]*$~~p'

Se você não tiver zsh, poderá usar ls e lidar com nomes de arquivos que contenham espaços, mas não com linhas novas ou espaços à direita, passando a opção -L1 para file . Isso invocou file em um arquivo por vez, então é um pouco mais lento.

ls -t | head -n 500 | xargs -L1 file --mime-type -- | sed -n 's~: *image/[^ ]*$~~p'
    
por 01.05.2015 / 23:49
-1

Você pode tentar

printf "%s
printf "%s%pre%" $(ls -t | head -500) | xargs -0 file | grep -v image
" $(ls -t | head -500) | xargs -0 file | grep -v image

Isso força o xargs a delimitar nulo os argumentos do nome do arquivo.

    
por 01.05.2015 / 16:29