У меня есть этот сценарий
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in $folder/*
do
touch $filePng.txt
done
Он работает, только для файла с именем 001.png
, он создает 001.png.txt
вместо 001.txt
.
Как я могу изменить это?
У меня есть этот сценарий
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in $folder/*
do
touch $filePng.txt
done
Он работает, только для файла с именем 001.png
, он создает 001.png.txt
вместо 001.txt
.
Как я могу изменить это?
Ответы:
Вы можете использовать basename
команду здесь:
touch "$folder/$(basename "$filePng" .png).txt"
Обратите внимание на дополнительное $folder/
. Это необходимо, поскольку команда basename удаляет путь из.
$filePng
- они тоже были полезны.
$( )
устанавливает новый контекст цитирования.
Вы можете удалить существующее расширение, используя функции расширения параметров оболочки
${parameter%pattern}
«Шаблон» сопоставляется с концом «параметра». Результатом является расширенное значение параметра с удалением кратчайшего соответствия.
Так что в вашем случае замените $filePng.txt
на"${filePng%.png}.txt"
В зависимости от того, что уже упоминалось в Steeldriver - расширение параметров - мы можем использовать замену строк для выполнения этой работы. Кроме того, вы должны заключать в кавычки переменные. Ниже ваш отредактированный скрипт.
#!/bin/bash
folder='/home/data/mnist/training'
for filePng in "$folder"/*
do
touch "${filePng/.png/.txt}"
done
Если у вас есть много файлов для создания, было бы целесообразно «дотронуться» более чем до одного файла за раз, чтобы вам не нужно было форкировать новый процесс для каждого из них (который занимает довольно много времени, если выполняется несколько тысячу раз).
xargs
Эта опция будет предоставлять несколько путей к touch
команде одновременно, обычно несколько тысяч или что угодно, что система может поместиться в одной командной строке.
find "$folder" -mindepth 1 -maxdepth 1 -name '*.png' -print0 |
sed -ze 's/\.png$/.txt/' |
xargs -r0 -- touch --
Эта опция вообще не запускается, touch
а использует функции оболочки Bash / Bourne / POSIX, которые вообще не требуют подпроцессов.
for f in "$folder"/*.png; do
: >> "${f%.png}.txt"
done
Если вы уверены, что у вас нет файлов с .png
серединой имени, вы можете просто использовать массив с расширением параметров:
pngs=( /path/to/pngs/*.png )
touch "${pngs[@]/.png/.txt}"
Это сохраняет все пути к файлам , заканчивающихся .png
в массиве , а затем использует параметр расширения для создания списка .txt
файлов, путем замены .png
на .txt
на каждом из них.
Имейте в виду, что это сломается, если у вас будет так много файлов, что все они не могут быть переданы в качестве аргументов для одного и того же вызова touch
.
for filePng in "$folder"/*
иtouch "$filePng".txt
- обратите внимание, что вы цитируете их только тогда, когда им предшествует$
.