Как перебирать файлы в каталоге с помощью Bash?
мне нужно написать сценарий, который запускает мою программу с разными аргументами, но я новичок в Bash. Я начинаю свою программу так:
./MyProgram.exe Data/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 if
end for
поэтому я действительно озадачен тем, как создать второй аргумент из первого, поэтому он выглядит как dataABCD_Log1.txt и запустите мою программу. Помощь очень ценится.
P.S. Я знаю, что есть аналогичные вопросы, но я нашел ничего о создании моего имени файла журнала.
4 ответов
пара заметок сначала: когда вы используете Data/data1.txt
в качестве аргумента, если это действительно должно быть /Data/data1.txt
(с ведущим слешем)? Кроме того, должен внешний цикл сканировать только для.txt файлы или все файлы в /Data? Вот ответ, предполагающий /Data/data1.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 (в том числе the / Data / part) -
$( ... )
запускает команду оболочки и вставляет ее вывод в этот момент в командной строке -
basename somepath .txt
выводит базовую часть somepath, С.txt удален с конца (например,/Data/file.txt
->file
)
Если вам нужно запустить MyProgram с Data/file.txt
вместо /Data/file.txt
используйте "${filename#/}"
убрать Слэш. С другой стороны, если это действительно Data
не /Data
вы хотите сканировать, просто используйте for filename in Data/*.txt
.
к сожалению для некромантии нить, но всякий раз, когда вы перебирать файлы по имени, это хорошая практика, чтобы избежать угловой случае, когда шар не совпадает (что делает переменная цикла и раскройте в (не-соответствия) Глоб шаблон строку).
например:
for filename in Data/*.txt; do
[ -e "$filename" ] || continue
# ... rest of the loop body
done
ссылки: Bash Подводные Камни
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##*/}
замена (расширение параметров оболочки) удаляет ведущий путь до последнего /
.
на base=${name%.txt}
замена удаляет замыкающие .txt
. Это немного сложнее, если расширения могут различаться.
то, что я использую, чтобы избежать дополнительных строк или проверок:
#!/bin/bash
for filename in $(find /Data/*.txt 2> /dev/null); do
for ((i=0; i<=3; i++)); do
./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
done
done
идея состоит в том, чтобы запустить поиск в подрешетке и отправить ошибки в /dev/null, чтобы вы никогда не перебирали ошибку об отсутствующих файлах.