Jag behöver skriva ett skript som startar mitt program med olika argument, men jag är ny i Bash. Jag startar mitt program med:
Jag startar mitt program med följande: ./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt]
.
Här är pseudokoden för vad jag vill göra:
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
Så jag är verkligen förbryllad över hur jag ska skapa det andra argumentet från det första, så att det ser ut som dataABCD_Log1.txt och starta mitt program.
Ett par anmärkningar först: när du använder Data/data1.txt
som ett argument, borde det egentligen vara /Data/data1.txt
(med ett snedstreck före)? Ska den yttre slingan endast söka efter .txt-filer eller alla filer i /Data? Här är ett svar som utgår från /Data/data1.txt
och endast .txt-filer:
#!/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
Anteckningar:
/Data/*.txt
expanderar till sökvägarna till textfilerna i /Data (inklusive /Data/ delen).$( ... )
kör ett skalkommando och infogar dess utdata vid den punkten i kommandoraden.basename somepath .txt
ger ut basdelen av somepath, med .txt borttagen från slutet (t.ex. /Data/file.txt
-> file
)Om du behöver köra MyProgram med Data/file.txt
istället för /Data/file.txt
, använd "${filename#/}"
för att ta bort det inledande snedstrecket. Om det å andra sidan verkligen är Data
och inte /Data
som du vill skanna, använd bara for filename in Data/*.txt
.
Ursäkta att jag inte har hittat en ny tråd, men när du itererar över filer genom att använda globbing är det bra att undvika hörnfallet där glob inte matchar (vilket gör att loop-variabeln expanderar till själva glob-mönstersträngen (som inte matchar)).
Till exempel:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
Referens: 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
Substitutionen name=${file###*/}
(shell parameter expansion)) tar bort det ledande söknamnet upp till det sista /
.
Substitutionen base=${name%.txt}
tar bort den avslutande .txt
. Det är lite knepigare om tilläggen kan variera.