работа со списком, когда некоторые строки содержат пробелы

Попробуйте использовать перенаправление стандартного вывода. Например

./program-name > myfile.log 2>&1

Другой метод

stdbuf -oL./program-name > myfile.log 2>&1 &

Я на iPad, не могу ссылаться на источники перенаправления atm.

0
22.08.2021, 20:19
2 ответа

Вам также не нужна строка -name a -prune -o name b c -prune..., поскольку на самом деле команда, которую вы запускаете, является не одной строкой, а несколькими строками. Просто когда вы пишете foo bar "a b", оболочка интерпретирует кавычки и разбивает командную строку на пробелы без кавычек, давая вам три строки foo, barи a b. Точно так же вы хотите в конечном итоге перейти к find— это аргументы -o, -name, a b, -pruneи т. д. Если у вас есть строка -o -name a b -prune, трудно сделать так, чтобы строка разделяется на другие пробелы, но не разделяется между aи b.

Во-первых, вам нужно каким-то образом прочитать список имен, разделенных новой строкой -, не разрывая отдельные строки. Поскольку вы упомянули Bash, для этого есть команда mapfile(readarray). Давайте пока предположим, что у вас есть этот список имен в другом файле. Затем

readarray -t names < listfile

заполнит массив namesсодержимым файла, по одной записи в строке.

Обратите внимание, что в вашем вопросе строка в myListтакже содержит обратную косую черту и пробелы перед вторым и третьим каталогами, которые вы, вероятно, захотите очистить, если будете хранить список таким образом. Или вы можете просто сохранить список как массив напрямую, как в ответе @James S. .


Затем вторая проблема заключается в построении списка аргументов для find. Там вам также нужен массив, чтобы сохранить аргументы нетронутыми и отдельными. Итак,

args=()
for n in "${names[@]}"; do
    args+=(-name "$n" -prune -o)
done

заполнит массив argsаргументами. Затем вы использовали бы его как

find... "${args[@]}"

Кроме того, вам не нужно повторять -prune, вы можете заключить все это в круглые скобки и просто иметь -pruneодин раз снаружи, например. в командной строке,вы бы использовали ... "(" -name this -o -name that ")" -prune..., и вы могли бы заполнить массив примерно так

args=("(")
for n in "${names[@]}"; do
    args+=(-name "$n" -o)
done
unset "args[${#args[@]} - 1]"  # remove the last -o
args+=( ")" -prune )

См.:

1
22.08.2021, 20:41

Я думаю, вы могли бы использовать специальную переменную IFS

 #!/bin/bash
OFS=$IFS
IFS=$'\n'

myList="a \\
        b c \\
        d"

dirList=
stringArray=($myList)
for i in "${stringArray[@]}" ; do
    dirList="$dirList -name $i -prune -o"
    echo "$dirList"
    echo " "
done
IFS=$OFS

Это заданный выход:

 -name a \ -prune -o
 
 -name a \ -prune -o -name         b c \ -prune -o
 
 -name a \ -prune -o -name         b c \ -prune -o -name         d -prune -o
0
23.08.2021, 00:28

Теги

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