Kako narediti zanko nad datotekami v imeniku in spremeniti pot ter dodati končnico imenu datoteke

Napisati moram skripto, ki zažene moj program z različnimi argumenti, vendar sem novinec v Bashu. Svoj program začnem z:

./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt].

Tukaj je psevdokoda za to, kar želim narediti:

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

Tako da sem res zmeden, kako iz prvega argumenta ustvariti drugega, da bo videti kot dataABCD_Log1.txt, in zagnati svoj program.

Rešitev

Najprej nekaj pripomb: ko kot argument uporabite Data/data1.txt, bi to res moralo biti /Data/data1.txt (z začetno poševnico)? Ali naj zunanja zanka išče samo datoteke .txt ali vse datoteke v /Data? Tukaj je odgovor, ki predvideva /Data/data1.txt in samo datoteke .txt:


#!/bin/bash
for filename in /Data/*.txt; do
    for ((i=0; i `file`)

Če želite program MyProgram zagnati z `Data/file.txt` namesto z `/Data/file.txt`, uporabite `"${filename#/}"`, da odstranite začetno poševnico. Po drugi strani pa, če res želite pregledati `Data` in ne `/Data`, uporabite `za ime datoteke v Data/*.txt`.
Komentarji (7)

Opravičujem se, da sem se vrnil na to temo, vendar je dobra praksa, da se izognete primeru, ko se globus ne ujema (zaradi česar se spremenljivka zanke razširi na sam niz globusa (ki se ne ujema)).

Na primer:

for filename in Data/*.txt; do
    [ -e "$filename" ] || continue
    # ... rest of the loop body
done

Referenca: Bash Pitfalls

Komentarji (9)
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

Zamenjava name=${file##*/} (shell parameter expansion) odstrani začetno ime poti do zadnjega /.

Zamenjava base=${name%.txt} odstrani končni .txt. Če se lahko razširitve razlikujejo, je to nekoliko bolj zapleteno.

Komentarji (2)