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