Πώς να κάνετε βρόχο σε αρχεία στον κατάλογο και να αλλάξετε τη διαδρομή και να προσθέσετε επίθημα στο όνομα αρχείου

Πρέπει να γράψω ένα σενάριο που να ξεκινάει το πρόγραμμά μου με διαφορετικά ορίσματα, αλλά είμαι νέος στο 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 `file`)

Αν χρειαζόταν να εκτελέσετε το MyProgram με `Data/file.txt` αντί για `/Data/file.txt`, χρησιμοποιήστε `"${filename#/}"` για να αφαιρέσετε την επικεφαλής κάθετο. Από την άλλη πλευρά, αν πραγματικά θέλετε να σαρώσετε το `Data` και όχι το `/Data`, απλά χρησιμοποιήστε `for filename in Data/*.txt`.
Σχόλια (7)

Συγγνώμη για τη νεκρομανία του νήματος, αλλά όποτε κάνετε επανάληψη σε αρχεία με globbing, είναι καλή πρακτική να αποφεύγετε τη γωνιακή περίπτωση όπου το glob δεν ταιριάζει (πράγμα που κάνει τη μεταβλητή του βρόχου να επεκτείνεται στο ίδιο το αλφαριθμητικό του προτύπου glob (που δεν ταιριάζει)).

Για παράδειγμα:

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

Αναφορά: Bash Pitfalls

Σχόλια (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

Η αντικατάσταση name=${file##*/} (shell parameter expansion) αφαιρεί το όνομα διαδρομής που προηγείται μέχρι το τελευταίο /.

Η υποκατάσταση base=${name%.txt} αφαιρεί το τέλος του .txt. Είναι λίγο πιο δύσκολο αν οι επεκτάσεις μπορούν να ποικίλουν.

Σχόλια (2)