Obtém o complemento do resultado de um comando ls

4

Digamos que eu tenha um diretório com vários arquivos, todos eles arquivos binários (arquivos sem extensões declaradas) e arquivos de origem ( .c extension). Eu faço isso:

$ ls

e obtenha:

README.md hello-world.c hello-world get-name.c get-name

e quero listar apenas arquivos com extensões específicas (digamos, .c e .md ), eu faço:

ls *.c *.md

e tudo bem!

Mas e se agora eu quiser excluir todos os arquivos que não têm a extensão .c ou .md , como posso fazer isso?

Eu sei como fazer isso para arquivos cujas extensões são conhecidas por mim, como:

ls *.c *.md | xargs rm

Mas como posso dizer à linha de comando para excluir os arquivos que NÃO correspondem aos meus critérios?

    
por rodrigoalves 11.02.2013 / 17:43

2 respostas

6

Use find :

find -maxdepth 1 ! -name "*.c" -print0 | xargs -0 ...

Observe que -maxdepth , -print0 , -r e -0 são encontrados em algumas implementações de find (foram introduzidos pelo GNU find / xargs ), mas não são especificados pelo POSIX. Outra maneira é, como Stéphane mencionou em seu comentário, usar a ação -exec de find - lembre-se de usar a forma -exec command {} + , pois reduz drasticamente o número de invocações de command (tem que permitir sintaxe onde os nomes dos arquivos são colocados no final, ou então você precisa colocar o command dentro de uma chamada sh -c ).

Como alternativa, grep a saída de ls

ls | grep -v "\.c$" | xargs ...

Você pode filtrar várias extensões com expressões regulares:

... | grep -v "\.\(c\|md\)$" | ...

com regexps prolongados:

... | grep -Ev "\.(c|md)$" | ...

com a opção de strings fixas (não coincide apenas com o final do nome do arquivo!):

... | grep -vF ".c
.md" | ...

ou encadeando mais grep s:

... | grep -v "\.c$" | grep -v "\.md$" | ...

Dito isso, find é provavelmente a melhor opção, já que com a opção -print0 ele manipula todos os caracteres possíveis em nomes de arquivos que podem precisar ser salvos de outra forma (contanto que find e xargs consigam trabalhar com NULL -terminadas cadeias de caracteres - por exemplo, as ferramentas GNU são).

    
por 11.02.2013 / 17:57
5

Em ksh , você pode usar:

rm -- !(*.c|*.md)

Essas extensões globbing também estão disponíveis em bash após shopt -s extglob e em zsh após setopt kshglob .

O seguinte é o equivalente nativo de zsh:

setopt extended_glob
rm -- ^(*.c|*.md)

O ! em um extglob é "não". Para o seu comando original, é preferível escrever isto:

rm -- *.c *.md

A análise da saída de ls não é confiável e interrompe alguns nomes de arquivos. Veja o bash wiki para analisando ls .

    
por 11.02.2013 / 17:51