C'è un modello comune in cui si hanno coppie di file, in cui un nome della coppia può essere facilmente derivato dall'altro. Se il file di cui si conosce il nome è X e l'altro file è Y, si hanno i seguenti casi d'uso comuni.
- Per la ridenominazione, Y è X con un'estensione rimossa e/o un timbro data aggiunto.
- Per la transcodifica, Y è X con un'estensione diversa e forse una directory diversa.
- Per molte attività di analisi dei dati, X e Y condividere alcune parti del nome del file, ma avere parametri o estensioni differenti.
Tutti questi si prestano allo stesso scheletro di codice approssimativo.
for x in path/to/base*.ext; do
dir=${x%/*} # Trim trailing file name, keep dir
base=${x##*/} # Trim any leading directory
# In this case, $y has a different subdirectory and a different extension
y=${dir%/to}/from/${base%.ext}.newext
# Maybe check if y exists? Or doesn't exist?
if [ -e "$y" ]; then
echo "$0: $y already exists -- skipping" >&2
continue
fi
mv or ffmpeg or awk or whatever "$x" and "$y"
done
La chiave qui è l'osservazione che y
può essere derivata dalla x
con alcune semplici sostituzioni variabili. Quindi si esegue il loop sui valori x
e si calcola il valore y
corrispondente all'interno del ciclo.
Qui, abbiamo utilizzato la shell integrato ${variable#prefix}
e ${variable%suffix}
operatori per restituire il valore della variabile con qualsiasi leader prefix
o finali suffix
, rispettivamente, rifilata. (C'è anche ##
e %%
per abbinare il più lungo, anziché più breve, possibile corrispondenza. L'espressione dopo #
o %
è una struttura regolare shell glob.Questi di solito dovrebbero essere tutto ciò che serve, anche se spesso vedi gli script sed
o awk
anche per questo lavoro banale (dove in realtà dovresti cercare di evitare un processo esterno), oltre naturalmente a trasformazioni più impegnative.
Se avete bisogno di ciclo oltre x
file sparsi per directory diverse, forse il ciclo dovrebbe iniziare con qualcosa di simile
find dir1 dir2 etc/and/so/forth -type f -name 'x-files*.ext' -print |
while IFS='' read -r x; do
:
Un problema comunemente visto in simili domande è risposte che non riescono a citare $x
e $y
correttamente. Generalmente, qualsiasi variabile contenente un nome di file dovrebbe sempre essere tra virgolette.
dove X e Y sono indipendenti, una soluzione comune è quello di loop su un documento qui contenente la mappatura:
while read -r x y; do
: stuff with "$x" and "$y"
done <<'____HERE'
first_x_value first_y_value
another_x corresponding_y
random surprise
____HERE
È necessario eseguire il looping sui prefissi e sui suffissi non sui nomi di file completi. –
Il comportamento che si ottiene è uguale a quello che un ciclo 'for' annidato farebbe in * qualsiasi * lingua; non c'è niente di specifico in proposito. –
Ogni volta che voglio fare qualcosa di relativamente semplice come iterare su coppie di valori, Bash rende il carico di lavoro un'epopea insormontabile. Quindi non uso bash quando ho bisogno di qualcosa di più complesso di un elenco di chiamate di shell. – ThorSummoner