C'è qualche vantaggio nel specificare './' in un ciclo for usando un glob?


10

Avevo l'impressione che potesse essere più sicuro usare ./*.fastqquando cercavo i file che finivano .fastq. Ad esempio, ./impedirebbe di acquisire il file .fastq. Questo è ovviamente sbagliato, come mostrato nell'esempio seguente:

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

*.fastq./*.fastqcorrispondere al file .fastq. Quindi mi chiedo ora, c'è qualche punto usando ./*.fastqqui, o ./*in generale?


1
Il solito punto ./*è che garantisce che i nomi che iniziano con -non vengano trattati come opzioni.
Charles Duffy,

Risposte:


15

Questo è inizialmente un comportamento jolly sorprendente, poiché la descrizione per il *carattere jolly dice:

Corrisponde a qualsiasi stringa, inclusa la stringa null.

... finché non ti rendi conto che quel periodo è leggermente speciale quando è il primo carattere di un nome file. Il testo introduttivo in 3.5.8 Filename Expansiondice:

Quando viene utilizzato un modello per l'espansione del nome file, il carattere '.' all'inizio di un nome file o immediatamente dopo una barra deve essere abbinato esplicitamente, a meno che non sia impostata l'opzione shell dotglob.

Il "modello di utilizzo" dei prefissi con caratteri jolly ./è utile per la gestione dei nomi con trattino iniziale nella shell bash , come ha commentato steeldriver. Non ha alcun effetto sull'espansione di caratteri jolly / nome file, ma rende più sicuro / più semplice gestire i nomi dei file quando li si fa riferimento, se iniziano con caratteri che tali programmi potrebbero interpretare erroneamente come opzioni. Per esempio:

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

... e ora che ho di avere un file chiamato -n, se mi capita di ciclo su di esso con un carattere jolly:

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

... non ottengo alcun output!

Ma se prefisso il carattere jolly con ./,

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

... vedo il nome del file.

Questo è un semplice esempio a scopo dimostrativo; vedi anche Perché printf è meglio dell'eco? per questo motivo e altri. Altre utilità verranno attivate da altre opzioni, quindi è meglio presentare i nomi dei file alle utility nel modo più sicuro possibile. Se non si antepone il carattere jolly per "sfuggire" ai nomi dei file, è necessario "proteggere" le utilità in altri modi; uno comune è quello di segnalare la fine delle opzioni con --, ad esempio:

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

... che passerà in modo sicuro il -nnome file a mv(come visto sotto set -x):

mv -- -n backup/-n
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.