Почему nullglob shopt -удаляет строку со знаком вопроса в элементе массива?

В этом скрипте есть несколько неправильных вещей, которые можно улучшить.

Основная проблема в вопросе, по-видимому, заключается в том, почему два вызова echoне производят никакого вывода.

Когда вы используете подстановку команд, как в

echo `rm file`

или эквивалент

echo $(rm file)

, то echoполучит вывод команды внутри обратных кавычек или внутри $(...). Ни одна из ваших замен команд не производит никакого вывода. Обе команды, которые вы используете в обратных кавычках, изменяют файлы, но опять же, ни одна из них не производит вывод в свой стандартный поток вывода (, который обычно отображается в терминале ). Это означает, что оба вызова echoтакже не дадут никаких результатов, за исключением пустой строки.

В целом, echo $(...)является анти-паттерном -, то есть вы можете делать то же самое гораздо лучше.

Если вы действительно хотите вывести результат какого-то конвейера pipeline, то вместо записи

echo $(pipeline)

вы бы сказали просто

pipeline

Будет отображаться вывод pipeline, так как вывод команд обычно отображается в терминале.

В приведенном ниже коде я вставил пару операторов printf, которые будут выводить соответствующую «информацию о ходе выполнения» в сценарии (s ).


Вот модифицированная версия скрипта, которая полностью не проверена (, так как у меня нет доступа к используемым вами инструментам или входным файлам ), но он должен имитировать то, что ваш скрипт делает, в том числе создает эти промежуточные файлы (они не нужны, а как от них избавиться я покажу позже ).

#!/bin/bash

export LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH"

timefmt="%C --- CPU:\t%E real,\t%U user,\t%S sys\t%P\tMem:\t%KkiB avg.,\t%MkiB max.\tExit:\t%x"

for dirpath in /input/sub-*/; do
    name=$(basename "$dirpath")
    id=${name#sub-}
    printf '%s\n' "$id"
    printf 'Found ID: %s\n' "$id" >&2
done | split -l 8 - participants_

for participants_id in participants_*; do
    ids=( $(<"$participants_id") )

    printf 'Processing ID: %s\n' "${ids[@]}" >&2

    /usr/bin/time -f "$timefmt" \
    fmriprep /input /output participant \
        --fs-license-file /opt/freesurfer/license.txt \
        --fs-no-reconall --use-aroma \
        --ignore fieldmaps --n_cpus 12 --force-bbr \
        --participant_label "${ids[@]}" \
        -w /output

    rm -f "$participants_id"
done

Исправления:

  1. Команда timeне обязательно должна быть псевдонимом только из-за наличия длинного аргумента опции для ее опции -f. Псевдонимы в любом случае не раскрываются в сценариях. Я просто сохраняю аргумент в строке и использую ее при вызове time.

  2. Ваш цикл добавляется к LD_LIBRARY_PATHв на каждой итерации. В этом не было необходимости.

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

  4. Вместо того, чтобы использовать findдля поиска промежуточных файлов, мы просто используем их с простым шаблоном подстановки имен файлов. Мы знаем, что они здесь и как их зовут.

  5. Только что обработанный промежуточный файл удаляется внутри цикла.

  6. Код делается читаемым за счет использования продолжений строк.

  7. Вызов waitудален. Никаких фоновых задач ждать не приходится.

В следующем варианте идентификаторы хранятся в массиве all_idsвместо временных файлов:

#!/bin/bash

export LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH"

timefmt="%C --- CPU:\t%E real,\t%U user,\t%S sys\t%P\tMem:\t%KkiB avg.,\t%MkiB max.\tExit:\t%x"

all_ids=( /input/sub-*/ )
all_ids=( "${all_ids[@]#/input/sub-}" ) # remove "/input/sub-" from each item
all_ids=( "${all_ids[@]%/}" )           # remove the trailing "/" from each item

printf 'Found ID: %s\n' "${all_ids[@]}" >&2

n=0
ids=( "${all_ids[@]:0:8}" ) # pick out the first eight IDs

# Loop until the first ID in the ids array is empty
while [ -n "${ids[0]}" ] ; do
    printf 'Processing ID: %s\n' "${ids[@]}" >&2

    /usr/bin/time -f "$timefmt" \
    fmriprep /input /output participant \
        --fs-license-file /opt/freesurfer/license.txt \
        --fs-no-reconall --use-aroma \
        --ignore fieldmaps --n_cpus 12 --force-bbr \
        --participant_label "${ids[@]}" \
        -w /output

    n=$(( n + 1 ))
    ids=( "${all_ids[@]:n*8:8}" ) # pick out the next eight IDs
done
1
10.08.2019, 12:48
0 ответов

Теги

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