У меня есть этот сценарий
#!/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- обратите внимание, что вы цитируете их только тогда, когда им предшествует$.