Que tal adicionar a opção globstar
shell e o -d
flag a ls
para não listar automaticamente o conteúdo do diretório?
shopt -s extglob
shopt -s globstar
ls -d **/!(*.c)
Gostaria de listar recursivamente todos os arquivos em um diretório que correspondam a um determinado padrão de entrada usando ls . (Ah, e isso é no Bash).
A única maneira que posso pensar em fazer isso usando ls é shopt -s extglob
e, em seguida, use a opção ls --ignore=pattern
com o padrão de negação de glob estendido !( pattern-list )
. Parece um tipo de rotatória para negar em um ignorar, mas de outra forma os curingas não são válidos.
Supondo que eu já tenha o diretório para procurar como dir
e o padrão para corresponder como file
, esta é minha tentativa atual:
ls -AR --ignore='!('"${file}"')' ${dir}
No entanto, isso não parece ter o efeito desejado, por exemplo, em um caso de teste em que a estrutura de diretórios fornece essa saída para ls -AR
:
.:
a a.c b b.c c c.h s
./s:
a a.c b b.c c c.h
Meu comando com file = *.c
e dir = s
(comando completo: ls -AR --ignore=!(*.c) s
) fornece esta saída:
./s:
a a.c b b.c c c.h
Eu sei que eu poderia canalizá-lo para o grep facilmente, e fazer algo como ls -AR s | grep -v '.*.c'
e obter uma saída como:
s:
a
b
c
c.h
mas estou procurando uma maneira de fazer isso apenas por meio de ls
.
Desculpe se não estava claro, esta é minha primeira vez em um site do StackExchange.
Obrigado antecipadamente!
GNU ls
--ignore
usa padrões de nome de arquivo padrão, e não ksh
estendida (que bash
(e bash
apenas, não ls
) reconhece com extglob
)
Então você pode fazer:
ls -AR --ignore='*.[ch]' --ignore='*.cpp'
Mas você não pode fazer:
ls -AR --ignore='!(*.[ch]|*.cpp)'
O que apenas ignoraria arquivos com o nome: !(foo.c|bar.cpp)
.
Em ls -AR --ignore=!(*.c)
, como o padrão não é citado, bash
tentaria expandi-lo antes de passá-lo para ls
. Por isso, no diretório atual, procuraria arquivos cujos nomes começassem com "--ignore="
e não terminassem em ".c"
. Por exemplo, se houvesse dois arquivos, um chamado --ignore=foo
e um chamado --ignore=bar
, ele executaria ls
com esses quatro argumentos: "ls"
, "-AR"
, "--ignore=bar"
, "--ignore=foo"
.
Você pode fazer (com o GNU find).
find . -regextype posix-extended -regex '.*\.([ch]|cpp)' -ls
Ou com qualquer POSIX find
:
find . \( -name '*.[ch]' -o -name '*.cpp' \) -exec ls -ld {} +
Ou supondo que não haja links simbólicos para os diretórios:
shopt -s extglob globstar dotglob failglob
ls -ld -- **/*.@([ch]|cpp)
Desta vez, bash
expande o padrão de globbing e passa a lista de arquivos para ls
.
Tags bash ls shell shell-script