Buscar files con extensiones dadas en arguments usando expresiones regulares

Digamos que tiene un siguiente command

search /home/user proc .h .c .txt ... 

Estoy construyendo un script con el command find para get todos los files que comienzan con un nombre de stack y terminan con una de las extensiones especificadas.

Me las he arreglado para build esto usando un bucle:

 directory=$1 fileName=$2 fileExtensions="" for arg in "$@" do #skipping first and second argument if [ $arg = $1 -o $arg = $2 ]; then continue; fi fileExtensions+="${arg//.}\|" done #removing the last '|', otherwise regex parser error occurs fileExtensions=${fileExtensions::-1} find $directory -name "$fileName*" -regex ".*\.\($fileExtensions)" 

¿Hay una manera más elegante de lograr esto usando regex?

¡Gracias por tu ayuda!

El script se puede networkingucir a:

 directory=$1 fileName=$2 shift 2 a="$*" b="${*#.}" (( ${#a} - ${#b} - $# )) && echo "some extension(s) is(are) missing a leading dot." >&2 fileExtensions="$(IFS=\|; echo "${*#.}")" find "$directory" -name "$fileName*" -regextype posix-egrep -regex ".*\.($fileExtensions)$" 

De forma pnetworkingeterminada, find acepta expresiones regulares de tipo emacs, para usar ese tipo son necesarias varias barras diagonales inversas, como \| . Eso podría evitarse usando un tipo diferente de expresiones regulares (como arriba).

Donde ${*#.} Elimina el punto inicial (si existe) y une todos los "Parámetros posicionales" restantes con el valor del primer carácter de IFS, que se configuró para ser | para la ejecución de la subshell.

Solo una asignación variable con una "Expansión de parameters", eso es todo lo que se necesita.


EDITAR
El (( ${#a} - ${#b} - $# )) se usa para verificar si todas las extensiones proporcionadas en la list de arguments comienzan con un punto.

El recuento de caracteres ( ${#a} ) de todos los arguments concatenados ( a=$* )
debe ser igual a
el recuento de caracteres ( ${#b} ) de todos los arguments concatenados (un punto inicial eliminado) ( b=${*#.} )
más
la cantidad de arguments ( $# ).

 ${#a} == ${#b} + $# 

Si y solo si todos los arguments tienen un punto inicial.

Como una testing aritmética:

 (( ${#a} - (${#b} + $#) )) 

O también:

 (( ${#a} - ${#b} - $# )) && echo "missing leading dot(s)." 

Editar II

La list de extensiones proporcionada en los arguments de línea de command se procesa aquí:

 fileExtensions="$(IFS=\|; echo "${*#.}")" 

Así es como funciona, de adentro hacia afuera:

 $* # This generates a string of all positional arguments using IFS. 

De LESS=+'/Special Parameters' man bash :

Es decir, "$ *" es equivalente a "$ 1c $ 2c …", donde c es el primer carácter del valor de la variable IFS.

Luego usamos "expansión de parameters" para cortar el frente de cada argumento posicional:

 ${parameter#word} # used as ${*# } above. 

De LESS=+/'parameter#word' man bash :

Si el parámetro es @ o *, la operación de eliminación de patrón se aplica sucesivamente a cada parámetro posicional, y la expansión es la list resultante.

La word en la expansión anterior se establece en un punto . , eliminando así los puntos al frente de todos los parameters posicionales.

Como el IFS en ese punto comienza con un | carácter, que se utiliza para build una cadena con | como el separador para la list de parameters que ha sido rayado de un punto en el frente.

Esa cadena se proporciona al command echo para imprimirlo.
Pero antes de que se ejecute el command echo, la variable $IFS se establece en a | .

Eso está envuelto dentro de una ejecución de command $(…) (para crear un subcarte que olvidará el cambio a IFS cuando termine).

Luego asignamos la cadena a una variable:

 fileExtensions="$(IFS=\|; echo "${*#.}")" 

En resumen: eso transforma .c .h .txt en c|h|txt .

Parece que la expresión regular debería funcionar, y la única otra opción que se me ocurre es algo así como -name "proc*" \( -name "*.c" -o -name "*.h" ... \) que probablemente no es mucho más simple.

Algunas cosas pequeñas que podrían hacerse:

1) Puede usar shift para deshacerse de $1 y $2 , en lugar del condicional dentro del bucle.

2) Podría combinar el -name y -regex , para que al final, tenga -regex ".*/proc.*\.(c|h|txt)"

3) Si desea acortar el código, puede unir los parameters posicionales con IFS y $* :

 $ set .c .h $ IFS='|' $ echo "(${*/./})" (c|h) 

(No digo nada sobre legibilidad o elegancia).