Как следует из комментариев, совместная группа - это «правильный» способ справиться с тем, что вы хотите. Но если это невозможно, вы можете использовать списки управления доступом, как вы предлагаете. Вы просто выполняете setfacl -m u: someuser: rwx thefolder
и повторяете для каждого пользователя, которому хотите предоставить доступ.
Обычный(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
при условии, что выходные данные не содержат NUL, вы также можете:
IFS= read -rd '' output < <(cmd)
Чтобы получить статус выхода cmd
, вы можете выполнить wait "$!"; ret=$?
в bash
, но не в zsh
.
Для полноты картины отметим, что 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
после команды))
Вы можете вывести символ после обычного вывода, а затем удалить его:
#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.