Ich muss ein Skript schreiben, das mein Programm mit verschiedenen Argumenten startet, aber ich bin neu in Bash. Ich starte mein Programm mit:
./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt]
.
Hier ist der Pseudocode für das, was ich tun möchte:
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
Ich bin wirklich verwirrt, wie ich das zweite Argument aus dem ersten erstellen kann. Es sieht also aus wie dataABCD_Log1.txt und startet mein Programm.
Ein paar Anmerkungen zuerst: Wenn Sie Data/data1.txt
als Argument verwenden, sollte es wirklich /Data/data1.txt
sein (mit einem führenden Schrägstrich)? Soll die äußere Schleife nur nach TXT-Dateien oder nach allen Dateien in/Data suchen? Hier ist eine Antwort unter der Annahme, dass nur /Data/data1.txt
- und .txt-Dateien vorhanden sind:
#!/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
Anmerkungen:
/Data/*.txt
erweitert die Pfade der Textdateien in/Data (einschließlich the/Data/part)$( ... )
führt einen Shell-Befehl aus und fügt seine Ausgabe an dieser Stelle in die Befehlszeile einbasename somepath .txt
gibt den Basisteil von somepath aus, wobei TXT vom Ende entfernt wird (z. B. /Data/file.txt
-> file
).Wenn Sie MyProgram mit Data/file.txt
anstelle von /Data/file.txt
ausführen mussten, entfernen Sie den führenden Schrägstrich mit "${filename#/}"
. Wenn es sich jedoch wirklich um Data
und nicht um /Data
handelt, den Sie scannen möchten, verwenden Sie einfach for filename in Data/*.txt
.
Es tut uns leid, dass Sie den Thread nicht synchronisiert haben, aber wenn Sie durch Globbing über Dateien iterieren, ist es ratsam, den Eckfall zu vermeiden, in dem der Glob nicht übereinstimmt (wodurch die Schleifenvariable auf den (nicht übereinstimmenden) Glob-Muster-String selbst erweitert wird).
Zum Beispiel:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
Hinweis: Bash Fallstricke
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
Die Ersetzung name=${file##*/}
( Shell-Parametererweiterung ) entfernt den führenden Pfadnamen bis zum letzten /
.
Die Ersetzung base=${name%.txt}
entfernt den nachfolgenden .txt
. Es ist etwas kniffliger, wenn die Erweiterungen variieren können.
Sie können die Ausgabeoption finds null mit read verwenden, um Verzeichnisstrukturen sicher zu durchlaufen.
#!/bin/bash
find . -type f -print0 | while IFS= read -r -d $'\0' file;
do echo "$file" ;
done
Also für deinen Fall
#!/bin/bash
find . -maxdepth 1 -type f -print0 | while IFS= read -r -d $'\0' file; do
for ((i=0; i<=3; i++)); do
./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
done
done
zusätzlich
#!/bin/bash
while IFS= read -r -d $'\0' file; do
for ((i=0; i<=3; i++)); do
./MyProgram.exe "$file" 'Logs/'"`basename "$file"`""$i"'.txt'
done
done < <(find . -maxdepth 1 -type f -print0)
führt die while-Schleife im aktuellen Bereich des Skripts (Prozesses) aus und ermöglicht, dass die Ausgabe von find bei Bedarf zum Festlegen von Variablen verwendet wird