Minun on kirjoitettava skripti, joka käynnistää ohjelmani eri argumenteilla, mutta olen uusi Bashissa. Käynnistän ohjelmani seuraavalla komennolla:
./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt]
.
Tässä on pseudokoodi siitä, mitä haluan tehdä:
for each filename in /Data do
for int i = 0, i = 3, i++
./MyProgram.exe Data/filename.txt Logs/filename_Log{i}.txt
end for
end for
Joten olen todella ymmälläni, miten luoda toinen argumentti ensimmäisestä, jotta se näyttää dataABCD_Log1.txt ja käynnistää ohjelmani.
Pari huomautusta ensin: kun käytät argumenttina Data/data1.txt
, pitäisikö sen oikeasti olla /Data/data1.txt
(etummaisen vinoviivan kanssa)? Pitäisikö ulomman silmukan skannata vain .txt-tiedostot vai kaikki tiedostot /Data-kansiossa? Tässä on vastaus, jossa oletetaan /Data/data1.txt
ja vain .txt-tiedostot:
#!/bin/bash
for filename in /Data/*.txt; do
for ((i=0; i<=3; i++)); do
./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
done
done
Huomautuksia:
/Data/*.txt
laajenee /Data-kohdassa olevien tekstitiedostojen poluiksi ( mukaan lukien /Data/-osa).$( ... )
suorittaa komentotulkkikomennon ja lisää sen tulosteen kyseiseen kohtaan komentorivillä.basename somepath .txt
antaa tulokseksi somepathin perusosan, jonka lopusta on poistettu .txt (esim. /Data/tiedosto.txt
-> tiedosto
).Jos sinun piti ajaa MyProgram Data/file.txt
eikä /Data/file.txt
, käytä "${tiedostonimi#/}"
poistaaksesi johtavan vinoviivan. Toisaalta, jos haluat todella skannata Data
eikä /Data
, käytä vain for filename in Data/*.txt
.
Anteeksi, että necromancing säiettä, mutta aina kun iteroida yli tiedostoja globbing, se's hyvä käytäntö välttää kulmatapaus, jossa glob ei täsmää (mikä tekee silmukka muuttuja laajentaa (un-matching) glob kuvio merkkijono itse).
Esimerkiksi:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
Viite: Bash Pitfalls
for file in Data/*.txt
do
for ((i = 0; i < 3; i++))
do
name=${file##*/}
base=${name%.txt}
./MyProgram.exe "$file" Logs/"${base}_Log$i.txt"
done
done
name=${tiedosto##*/}
-korvaus (shell parameter expansion) poistaa johtavan polunnimen viimeiseen /
asti.
Korvaus base=${nimi%.txt}
poistaa perässä olevan .txt
. Se'on hieman hankalampaa, jos laajennukset voivat vaihdella.