¿Hay alguna ventaja en especificar './' en un bucle for usando un glob?

10

Tenía la impresión de que podría ser más seguro usarlo ./*.fastqcuando busque archivos que terminen en .fastq. Por ejemplo, ./evitaría capturar el archivo .fastq. Esto obviamente es incorrecto, como se muestra en el siguiente ejemplo:

TMP_DIR=$(mktemp --directory)
mkdir -p ${TMP_DIR}
(cd ${TMP_DIR}
 touch {a,b,c,}.fastq
 ls -a
 echo ""

 echo "# match all:"
 for f in *.fastq ; do
     echo "${f}"
 done
 echo ""

 echo "# with ./:"
 for f in ./*.fastq ; do
     echo "${f}"
 done
)
rm -rf ${TMP_DIR}
.
..
a.fastq
b.fastq
c.fastq
.fastq

# match all:
a.fastq
b.fastq
c.fastq

# with ./:
./a.fastq
./b.fastq
./c.fastq

Ni *.fastqtampoco ./*.fastqcoincide con el archivo .fastq. Entonces, me pregunto, ¿hay algún punto para usar ./*.fastqaquí, o ./*en general?

Frédéric Mahé
fuente
1
El punto habitual ./*es que garantiza que los nombres que comienzan con -no sean tratados como opciones.
Charles Duffy

Respuestas:

15

Inicialmente, eso es un comportamiento sorprendente de comodín, ya que la descripción del *carácter comodín dice:

Coincide con cualquier cadena, incluida la cadena nula.

... hasta que te des cuenta de que el período es ligeramente especial cuando es el primer carácter de un nombre de archivo. El texto introductorio en lo 3.5.8 Filename Expansiondice:

Cuando se usa un patrón para la expansión del nombre de archivo, el carácter '.' al comienzo de un nombre de archivo o inmediatamente después de una barra debe coincidir explícitamente, a menos que se establezca la opción de shell dotglob.

El "patrón de uso" de prefijar comodines con ./es útil para manejar nombres con guiones iniciales en bash shell , como comentó steeldriver. No tiene ningún efecto sobre la expansión del comodín / nombre de archivo, pero hace que sea más seguro / fácil manejar los nombres de archivo cuando se hace referencia a ellos, si comienzan con caracteres que esos programas podrían malinterpretar como opciones. Por ejemplo:

# I want a file named `-n`
$ touch -n
touch: invalid option -- 'n'
Try 'touch --help' for more information.
$ touch -- -n
### ok
$ touch ./-n
### ok

... y ahora que tengo un archivo llamado -n, si sucede que lo recorro con un comodín:

for file in *n
do
  echo "$file"
done

... no tengo salida!

Pero si prefijo el comodín con ./,

for file in ./*n
do
  echo "$file"
done
./-n

... veo el nombre del archivo.

Este es un ejemplo simple para fines de demostración; ver también ¿Por qué es printf mejor que echo? Por este motivo y otros. Otras utilidades se verán disparadas por otras opciones, por lo que es mejor presentar los nombres de archivo a las utilidades de la manera más segura posible. Si no prefijas el comodín para "escapar" de los nombres de archivo, tendrás que "proteger" tus utilidades de otras maneras; uno común es señalar el final de las opciones con --, por ejemplo:

for file in *n
do
  mv -- "$file" backup/"$file"
done

... que pasará con seguridad el -nnombre de archivo a mv(como se ve debajo set -x):

mv -- -n backup/-n
Jeff Schaller
fuente