Как перебирать подкаталоги и выполнять действия, игнорируя пробелы в именах файлов

В этом ответе я дам только общие советы, а не тесты. Бенчмарки — единственный способ достоверно ответить на вопросы о производительности. Но так как вы не говорите сколько данных вы обрабатываете и как часто вы выполняете эту операцию, нет никакого способа провести полезный тест. Что более эффективно для 10 элементов и что более эффективно для 1000000 элементов, часто не одно и то же.

Как правило, вызов внешних команд обходится дороже, чем выполнение каких-либо действий с конструкциями чистой оболочки, если код чистой оболочки не включает цикл. С другой стороны, цикл оболочки, который перебирает большую строку или большое количество строк, скорее всего, будет медленнее, чем один вызов специального -целевого инструмента. Например, ваш цикл, вызывающий cut, вполне может быть заметно медленным на практике, но если вы найдете способ сделать все это с помощью одного вызова cut, это, вероятно, будет быстрее, чем делать то же самое с манипуляциями со строками в оболочка.

Обратите внимание, что точка отсечки может сильно различаться в разных системах. Это может зависеть от ядра, от того, как настроен планировщик ядра, от файловой системы, содержащей внешние исполняемые файлы, от того, насколько велика нагрузка на процессор и память в данный момент, и от многих других факторов.

Не вызывайте exprдля выполнения арифметических операций, если вас вообще беспокоит производительность. На самом деле, вообще не вызывайте exprдля выполнения арифметических операций. Оболочки построили -в арифметике, которая понятнее и быстрее, чем вызов expr.

Кажется, вы используете bash,поскольку вы используете конструкции bash, которых нет в sh. Так почему бы вам не использовать массив? Массив — наиболее естественное решение, и, вероятно, оно также будет самым быстрым. Обратите внимание, что индексы массива начинаются с 0.

list=(1 2 3 5 9 8 6 90 84 9 3 2 15 75 55)
for ((count = 0; count += 3; count < ${#list[@]})); do
  echo "${list[$count]}"
done

Ваш скрипт может быть быстрее, если вы используете sh, если в вашей системе есть dash или ksh как sh, а не bash. Если вы используете sh, вы не получаете именованные массивы, но вы все равно получаете массив с одним из позиционных параметров, который вы можете установить с помощью set. Чтобы получить доступ к элементу в позиции, которая неизвестна до времени выполнения, вам нужно использоватьeval(позаботьтесь о правильном цитировании! ).

# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
count=1
while [ $count -le $# ]; do
  eval "value=\${$count}"
  echo "$value"
  count=$((count+1))
done

Если вы хотите получить доступ к массиву только один раз и перемещаетесь слева направо (, пропуская некоторые значения ), вы можете использовать shiftвместо индексов переменных.

# List elements must not contain whitespace or ?*\[
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
set $list
while [ $# -ge 1 ]; do
  echo "$1"
  shift && shift && shift
done

Какой подход быстрее, зависит от оболочки и количества элементов.

Другой возможностью является использование обработки строк. Его преимущество в том, что он не использует позиционные параметры, поэтому вы можете использовать их для чего-то другого. Это будет медленнее для больших объемов данных, но вряд ли это будет иметь заметное значение для небольших объемов данных.

# List elements must be separated by a single space (not arbitrary whitespace)
list='1 2 3 5 9 8 6 90 84 9 3 2 15 75 55'
while [ -n "$list" ]; do
  echo "${list% *}"
  case "$list" in *\ *\ *\ *) :;; *) break;; esac
  list="${list#* * * }"
done
0
26.01.2021, 18:41
1 ответ

«Имена файлов с пробелами» требуют findи xargs. Прочтите man find xargsи сделайте что-то вроде

find Fixed_Zip -type f -name '*.ipynb' -print0 | \
    xargs -0 -r -n 1 jupytext --to py
1
18.03.2021, 22:34

Теги

Похожие вопросы