Πρέπει να γράψω ένα σενάριο που να ξεκινάει το πρόγραμμά μου με διαφορετικά ορίσματα, αλλά είμαι νέος στο Bash. Ξεκινάω το πρόγραμμά μου με:
Δεδομένα/data1.txt [Logs/data1_Log.txt]`.
Εδώ είναι ο ψευδοκώδικας για αυτό που θέλω να κάνω:
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
Έτσι, είμαι πραγματικά προβληματισμένος πώς να δημιουργήσω το δεύτερο όρισμα από το πρώτο, έτσι ώστε να μοιάζει με το dataABCD_Log1.txt και να ξεκινήσω το πρόγραμμά μου.
Μερικές σημειώσεις πρώτα: όταν χρησιμοποιείτε το Data/data1.txt
ως όρισμα, θα πρέπει να είναι πραγματικά /Data/data1.txt
(με μια επικεφαλής κάθετο); Επίσης, θα πρέπει ο εξωτερικός βρόχος να σαρώνει μόνο για αρχεία .txt ή για όλα τα αρχεία στο /Data; Ακολουθεί μια απάντηση, υποθέτοντας /Data/data1.txt
και μόνο αρχεία .txt:
#!/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
Σημειώσεις:
/Data/*.txt
επεκτείνεται στις διαδρομές των αρχείων κειμένου στο /Data (συμπεριλαμβανομένου του μέρους /Data/)$( ... )
εκτελεί μια εντολή κελύφους και εισάγει την έξοδό της στο συγκεκριμένο σημείο της γραμμής εντολώνbasename somepath .txt
εξάγει το βασικό μέρος του somepath, με την αφαίρεση του .txt από το τέλος (π.χ. /Data/file.txt
-> file
)Αν χρειαζόταν να εκτελέσετε το MyProgram με Data/file.txt
αντί για /Data/file.txt
, χρησιμοποιήστε "${filename#/}"
για να αφαιρέσετε την επικεφαλής κάθετο. Από την άλλη πλευρά, αν πραγματικά θέλετε να σαρώσετε το Data
και όχι το /Data
, απλά χρησιμοποιήστε for filename in Data/*.txt
.
Συγγνώμη για τη νεκρομανία του νήματος, αλλά όποτε κάνετε επανάληψη σε αρχεία με globbing, είναι καλή πρακτική να αποφεύγετε τη γωνιακή περίπτωση όπου το glob δεν ταιριάζει (πράγμα που κάνει τη μεταβλητή του βρόχου να επεκτείνεται στο ίδιο το αλφαριθμητικό του προτύπου glob (που δεν ταιριάζει)).
Για παράδειγμα:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
Αναφορά: 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=${file##*/}
(shell parameter expansion) αφαιρεί το όνομα διαδρομής που προηγείται μέχρι το τελευταίο /
.
Η υποκατάσταση base=${name%.txt}
αφαιρεί το τέλος του .txt
. Είναι λίγο πιο δύσκολο αν οι επεκτάσεις μπορούν να ποικίλουν.