Ho questa sceneggiatura
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in $folder/*
do
touch $filePng.txt
done
Funziona, solo che, per un file chiamato 001.png
, crea 001.png.txt
invece di 001.txt
.
Come posso modificarlo?
Ho questa sceneggiatura
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in $folder/*
do
touch $filePng.txt
done
Funziona, solo che, per un file chiamato 001.png
, crea 001.png.txt
invece di 001.txt
.
Come posso modificarlo?
Risposte:
Puoi usare il basename
comando qui:
touch "$folder/$(basename "$filePng" .png).txt"
Nota l'ulteriore $folder/
. Questo è necessario poiché il comando basename rimuove il percorso da.
$filePng
: erano anche utili.
$( )
stabilisce un nuovo contesto di quotazione.
È possibile rimuovere l'estensione esistente utilizzando le funzionalità di espansione dei parametri della shell
${parameter%pattern}
Il "modello" è abbinato alla fine del "parametro". Il risultato è il valore espanso di "parametro" con la corrispondenza più breve eliminata.
Quindi, nel tuo caso, sostituiscilo $filePng.txt
con"${filePng%.png}.txt"
Con la variazione di quanto già detto steeldriver - espansione dei parametri - possiamo usare la sostituzione di stringhe per fare il lavoro. Inoltre, dovresti citare le variabili. Di seguito è riportato il tuo script modificato.
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in "$folder"/*
do
touch "${filePng/.png/.txt}"
done
Se hai molti file da creare, varrebbe la pena "toccare" più di un file alla volta, quindi non è necessario eseguire il fork di un nuovo processo per ciascuno di essi (che richiede parecchio tempo se eseguito in più mille volte).
xargs
Questa opzione fornirà più percorsi al touch
comando contemporaneamente, di solito qualche migliaio o qualunque cosa il sistema possa adattare su una singola riga di comando.
find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --
Questa opzione non funziona touch
affatto ma utilizza invece le funzionalità della shell Bash / Bourne / POSIX che non richiedono affatto processi secondari.
for f in "$folder"/*.png; do
: >> "${f%.png}.txt"
done
Se sei sicuro di non avere file con .png
qualcosa nel mezzo del nome, puoi semplicemente usare un array con espansione dei parametri:
pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"
Questo memorizza tutti i percorsi dei file che finiscono in .png
un array e quindi utilizza l'espansione dei parametri per creare l'elenco di .txt
file, sostituendo .png
per .txt
ognuno.
Tieni presente che questo si interromperà se hai così tanti file che non possono essere passati tutti come argomenti alla stessa invocazione di touch
.
for filePng in "$folder"/*
etouch "$filePng".txt
- nota che li citi solo quando preceduto da a$
.