Gostaria de listar todos os arquivos em uma pasta chamada que foldername
possui a extensão test
ou atest
.btest
Meu pensamento imediato foi correrls ./foldername/*.{a,b,}test
Isso funciona bem, a menos que não haja nada com a extensão atest
; nesse caso, recebo o erro zsh: no matches found: ./foldername/*.atest
.
Existe alguma maneira de simplesmente ignorar esse erro e imprimir os arquivos que existem?
Preciso que isso funcione tanto no zsh quanto no Bash.
Responder1
Em
ls -d ./foldername/*.{a,b,}test
{a,b,...}
não é um operador glob, é uma expansão de chaves, que é primeiro expandida para:
ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test
E cada glob foi expandido individualmente e, se algum glob não corresponder, o comando será cancelado conforme esperado zsh
(ou fish
; in bash
, você precisa da failglob
opção para obter um comportamento semelhante).
Aqui, você deseja usar um único glob que corresponda a todos esses arquivos e cancelar o comando apenas se esse glob não corresponder a nenhum arquivo:
ls -d ./foldername/*.(a|b|)test
Você não deseja usar nullglob
, como se nenhum dos globs correspondesse, ele seria executado ls
sem argumentos, então liste o diretório atual. cshnullglob
é melhor nesse aspecto, pois remove globos não correspondentes, mas ainda cancela o comando se todos os globos não corresponderem.
Você não gostaria de usar nonomatch
, pois isso lhe daria um comportamento quebrado, bash
o que seria uma pena.
Para uma alternativa glob que funcione em zsh
and bash
, você pode usar os ksh globs ( set -o kshglob
in zsh
e shopt -s extglob
in bash
).
Então, você faria:
ls -d ./foldername/*.@(a|b|)test
ou:
ls -d ./foldername/*.?([ab])test
Adicione a failglob
opção bash
para evitar que o glob seja passado literalmente ls
quando não corresponder.
VerPor que nullglob não é padrão?Para maiores informações.
Responder2
Talvez seja melhor fazer isso com find
:
find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
Responder3
Eu enfrentei esse problema e primeiro o resolvi hackeando o próprio ls. Quando terminei, percebi que tudo que eu precisava era do programa trival C:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
struct stat statbuf;
int i;
for( i=1; i<argc; i++ ) {
if( stat(argv[i],&statbuf) == 0 ) {
printf("%s\n",argv[i]);
}
}
}
Tudo o que isso faz, e tudo o que precisa fazer, é percorrer seus argumentos de linha de comando e ecoar aquelas strings que correspondem a arquivos válidos (isto é, para os quais stat() é bem-sucedido).
Claro, podemos emular isso com Python, Perl igualmente simples ou até mesmo uma função shell que executa stat, mas escrevê-lo em C torna sua execução muito mais rápida.
Quanto a hackear ls, dei uma olhada em meu wiki pessoal:http://linux.chalisque.net/LsIgnoreMissing
Responder4
O comentário de @DopeGhoti funcionou para mim.
ou seja, redirecionando o erro para /dev/null
usar 2>
o operador assim:
ls ./foldername/*.{a,b,}test 2> /dev/null