оболочка: сохраняйте завершающие символы новой строки ('\ n') в подстановке команд

Как следует из комментариев, совместная группа - это «правильный» способ справиться с тем, что вы хотите. Но если это невозможно, вы можете использовать списки управления доступом, как вы предлагаете. Вы просто выполняете setfacl -m u: someuser: rwx thefolder и повторяете для каждого пользователя, которому хотите предоставить доступ.

14
02.08.2017, 14:24
2 ответа

Оболочки POSIX

Обычный(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 )Чтобы получить полный стандартный вывод команды, нужно сделать:

output=$(cmd; ret=$?; echo.; exit "$ret")
ret=$?
output=${output%.}

Идея состоит в том, чтобы добавить дополнительный .\n. Подстановка команд удалит только и\n. И вы разделите .с ${output%.}.

Обратите внимание, что в оболочках, отличных от zsh, это все равно не будет работать, если на выходе есть байты NUL. С yashэто не сработает, если вывод не является текстом.

Также обратите внимание, что в некоторых локалях важно, какой символ вы используете для вставки в конце. .обычно должно быть хорошо, но некоторые другие могут не работать. Например, x(, используемый в некоторых других ответах )или @, не будет работать в локали с использованием кодировок BIG5, GB18030 или BIG5HKSCS. В этих кодировках кодировка ряда символов заканчивается тем же байтом, что и кодировка xили@(0x78, 0x40)

Например, ūв BIG5HKSCS — это 0x88 0x78 (и x— это 0x78, как и в ASCII, все наборы символов в системе должны иметь одинаковую кодировку для всех символов переносимого набора символов, который включает английские буквы., @и .). Таким образом, если cmdбыло printf '\x88'и мы вставили xпосле него, ${output%x}не смогло бы удалить это x, поскольку $outputфактически содержало бы ū.

Использование .вместо этого может привести к той же проблеме в теории, если бы были какие-либо символы, кодировка которых заканчивается той же кодировкой, что и ., но, проверив некоторое время назад, я могу сказать, что ни одна из кодировок, которые может быть доступен для использования в локали в Debian,В системах FreeBSD или Solaris есть такие символы, которые меня вполне устраивают (, и поэтому я остановился на ., который также является символом для обозначения конца предложения в английском языке, поэтому кажется подходящим ).

Более правильным подходом, как , обсуждаемым @Isaac , было бы изменение языкового стандарта на C только для удаления последнего символа (${output%.}), что обеспечило бы удаление только одного байта, но это было бы значительно усложнить код и потенциально создать собственные проблемы совместимости.

альтернативы bash/zsh

С bashи zshпри условии, что выходные данные не содержат NUL, вы также можете:

IFS= read -rd '' output < <(cmd)

Чтобы получить статус выхода cmd, вы можете выполнить wait "$!"; ret=$?в bash, но не в zsh.

rc/es/akanaga

Для полноты картины отметим, что rc/es/akangaимеют для этого оператор. В них подстановка команд, выраженная как`cmd(или `{cmd}для более сложных команд ), возвращает список (путем разбиения на $ifs, пробел -, вкладку -, новую строку по умолчанию ). В этих оболочках (, в отличие от Bourne -, подобных оболочкам ), удаление новой строки выполняется только как часть этого $ifsразбиения. Таким образом, вы можете либо очистить $ifs, либо использовать форму ``(seps){cmd}, где вы указываете разделители:

ifs = ''; output = `cmd

или:

output = ``()cmd

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

рыба

В fish подстановка команд осуществляется с помощью (cmd)и не включает подоболочку.

set var (cmd)

Создает массив $varсо всеми строками на выходе cmd, если $IFSне -пуст, или с выходом cmd, лишенным до одной(в отличие от все в большинстве других оболочек )символ новой строки, если $IFSпусто.

Таким образом, по-прежнему существует проблема, заключающаяся в том, что (printf 'a\nb')и (printf 'a\nb\n')расширяются до одного и того же, даже если $IFSпуст.

Чтобы обойти это, лучшее, что я мог придумать, это:

function exact_output
  set -l IFS. # non-empty IFS
  set -l ret
  set -l lines (
    cmd
    set ret $status
    echo
  )
  set -g output ''
  set -l line
  test (count $lines) -le 1; or for line in $lines[1..-2]
    set output $output$line\n
  end
  set output $output$lines[-1]
  return $ret
end

Альтернативой является:

read -z output < (begin; cmd; set ret $status; end | psub)

Оболочка Борна

Оболочка Bourne не поддерживает ни форму $(...), ни оператор ${var%pattern}, поэтому добиться этого там может быть довольно сложно. Один из подходов — использовать eval и цитирование :

.
eval "
  output='`
    exec 4>&1
    ret=\`
      exec 3>&1 >&4 4>&-
      (cmd 3>&-; echo \"\$?\" >&3; printf \"'\") |
        awk 3>&- -v RS=\\\\' -v ORS= -v b='\\\\\\\\' '
          NR > 1 {print RS b RS RS}; {print}; END {print RS}'
    \`
    echo \";ret=\$ret\"
  `"

Здесь мы генерируем

output='output of cmd
with the single quotes escaped as '\''
';ret=X

для передачи eval. Что касается POSIX-подхода, если бы 'был одним из тех символов, кодировка которых может быть найдена в конце других символов, у нас была бы проблема (, гораздо более серьезная, поскольку она стала бы уязвимостью для внедрения команд ). ], но, к счастью, как и ., это не один из них, и этот метод цитирования обычно используется всем, что цитирует шелл-код (обратите внимание, что \имеет проблему, поэтому не должно быть используемый (также исключает "...", внутри которого вам нужно использовать обратную косую черту для некоторых символов ). Здесь мы используем его только после ', что нормально ).

ткш

См. tcsh сохраняет новые строки при подстановке команд `...`

(не заботиться о статусе выхода, который можно решить, сохранив его во временном файле(echo $status > $tempfile:qпосле команды))

23
27.01.2020, 19:50

Вы можете вывести символ после обычного вывода, а затем удалить его:

#capture the output of "$@" (arguments run as a command)
#into the exact_output` variable
exact_output() 
{
    exact_output=$( "$@" && printf X ) && 
    exact_output=${exact_output%X}
}

Это решение соответствует стандарту POSIX.

2
27.01.2020, 19:50

Теги

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