Me gustaría enumerar todos los archivos en una carpeta llamada que foldername
tiene la extensión test
o atest
.btest
Mi pensamiento inmediato fue correrls ./foldername/*.{a,b,}test
Esto funciona bien a menos que no haya nada con la extensión atest
, en cuyo caso aparece el error zsh: no matches found: ./foldername/*.atest
.
¿Hay alguna manera de ignorar este error e imprimir los archivos que existen?
Necesito que esto funcione tanto en zsh como en Bash.
Respuesta1
En
ls -d ./foldername/*.{a,b,}test
{a,b,...}
no es un operador global, eso es una expansión de llaves, que primero se expande a:
ls -d ./foldername/*.atest ./foldername/*.btest ./foldername/*.test
Y cada globo se expandió individualmente, y si algún globo no coincide, el comando se cancela como era de esperar en zsh
(o fish
; en bash
, necesita la failglob
opción para obtener un comportamiento similar).
Aquí, querrás usar un solo globo que coincida con todos esos archivos y solo cancelar el comando si ese globo no coincide con ningún archivo:
ls -d ./foldername/*.(a|b|)test
No desea utilizar nullglob
, ya que si ninguno de los globos coincidiera, se ejecutaría ls
sin argumentos, así que indique el directorio actual. cshnullglob
es mejor en ese sentido, ya que elimina los globos que no coinciden pero aun así cancela el comando si todos los globos no coinciden.
No querrás usarlo nonomatch
, ya que eso te daría un comportamiento roto, bash
lo cual sería una pena.
Para obtener una alternativa global que funcione tanto en zsh
como en bash
, puede usar ksh globs ( set -o kshglob
in zsh
y shopt -s extglob
in bash
).
Entonces, harías:
ls -d ./foldername/*.@(a|b|)test
o:
ls -d ./foldername/*.?([ab])test
Agregue la failglob
opción bash
para evitar que el globo se pase literalmente ls
cuando no coincida.
Ver¿Por qué nullglob no es el predeterminado?para más información.
Respuesta2
Quizás sea mejor hacer esto con find
:
find ./foldername -maxdepth 1 -name '*.atest' -o -name '*.btest' -o -name '*.test'
Respuesta3
Me enfrenté a este problema y primero lo resolví pirateando el propio ls. Cuando terminé, me di cuenta de que todo lo que necesitaba era el 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]);
}
}
}
Todo lo que esto hace, y todo lo que necesita hacer, es ejecutar los argumentos de su línea de comando y repetir aquellas cadenas que corresponden a archivos válidos (es decir, para los cuales stat() tiene éxito).
Por supuesto, podemos emular esto con Python, Perl o incluso una función de shell que ejecute stat, igualmente simple, pero escribirlo en C hace que su ejecución sea mucho más rápida.
En cuanto a piratear ls, lo revisé en mi wiki personal:http://linux.chalisque.net/LsIgnoreMissing
Respuesta4
El comentario de @DopeGhoti funcionó para mí.
es decir, redirigir el error al /dev/null
uso 2>
del operador de esta manera:
ls ./foldername/*.{a,b,}test 2> /dev/null