Sudo создает переменную окружения "SUDO_USER", которую вы можете использовать для определения пользователя, который вошел в систему (на самом деле, кто запускал Sudo).
Предполагая, что вы используете Sudo как root (можно использовать Sudo и для доступа к другим пользователям), вы можете написать сценарий для автоматизации следующих двух шагов.
cp source target
chown $SUDO_USER target
(Это не сработает, если вы выполните sudo для пользователя без полномочий root, поскольку только root может отдавать файлы.)
Автоматизация этого процесса потребует немного усилий. Если источник - это один файл, а цель - не каталог, то ваша работа сделана. Я предполагаю, что вы задали вопрос, потому что проблема возникает только в более сложных ситуациях, например, когда вы делаете что-то вроде:
cp / path / source / some * files / path / target / directory /
Сложный скрипт, чтобы выяснить, какие файлы и какие каталоги переданы, какие из них существовали ранее, какие были фактически перезаписаны, а также для изменения владельца только успешно скопированных файлов.
Эта работа уже проделана. Вы можете использовать cpio
- После sudo для получения root-прав используйте cpio для копирования файлов. cpio нужен список файлов для копирования, поэтому это двухэтапный процесс. Ниже я использую ls
для создания списка файлов для копирования.
ls / путь / источник / некоторые * файлы | cpio -pdm --owner $ SUDO_USER / path / target / directory /
-pdm
означает «Режим сквозной передачи, создавать каталоги по мере необходимости, поддерживать время изменения файла»
- владелец $ SUDO_USER "
заставляет указанного пользователя владеть файлами.
Последний операнд - это каталог, в котором cpio должен хранить файлы.
Чтобы узнать больше о возможностях cpio, перейдите на страницу руководства CPIO здесь
Это также возможно с помощью одной команды sudo. Предполагая, что ваш пользователь имеет права на доступ к файлам, используйте sudo только для части cpio, например:
ls / path / source / some * files | cpio - pdm --owner $ USER / path / target / directory /
В приведенном выше случае я использую $ USER вместо $ SUDO_USER, потому что он оценивается перед запуском Sudo. В качестве альтернативы, если у пользователя нет доступа к перечислите файлы, поместите его в сценарий оболочки и используйте sudo для запуска оболочки. Это может стать сложнее, но в простейшем случае оболочка принимает два аргумента, источник и цель.
Thi s входит в оболочку cp_as_user:
ls $ 1 | cpio -pdm --owner $ SUDO_USER $ 2
Затем используйте такую оболочку:
sudo cp_as_user "/ path / to / some * files" / path / to / target / directory
El problema con $($(echo $z))
es que se expande, primero a$(1)
(si $z
es 1 )y luego el shell intenta ejecutar 1
como un comando.
Suponiendobash
:
params=( "$@" )
for (( i = 0; i < ${#params[@]}; ++i )); do
printf 'Param %d is "%s"\n' "$i" "${params[i]}"
done
Ejecutarlo:
$ bash script.sh a b c
Param 0 is "a"
Param 1 is "b"
Param 2 is "c"
O, con/bin/sh
:
i=0
while [ "$#" -gt 0 ]; do
printf 'Param %d is "%s"\n' "$i" "$1"
i=$(( i + 1 ))
shift
done
Ejecutando eso:
$ /bin/sh script.sh a b c
Param 0 is "a"
Param 1 is "b"
Param 2 is "c"
Eso es si realmente necesita enumerarlos explícitamente. Por lo general, uno simplemente repetiría"$@"
:
for param in "$@"; do
printf 'Param: "%s"\n' "$param"
# do other thing with "$param" here
done
for z in 1..$(seq 1 $#);
Eso se expandiría a 1..1
, 2
, 3
para tres parámetros. seq
ya imprime los números como palabras distintas, y for
realmente no puede generar listas de números. La expansión de llaves puede generar listas de números, la sintaxis es {1..3}
, pero en Bash no admite variables en su interior.
Así que esto podría escribirse como
for z in $(seq $#) ; do... # or
for (( z=1 ; z <= $# ; z++ )) ; do...
o con llaves en ksh o zsh:
for z in {1..$#} ; do ...
Si desea referirse a una variable indirectamente, puede usar${!var}
(en Bash )donde var
contiene el nombre de la variable, por ejemplo,.
echo "param number $z is ${!z}"
Alternativamente, podría usar la notación de corte en$@
(debería funcionar en Bash/ksh/zsh):
echo "param number $z is ${@:z:1}"
Pero en realidad, simplemente usar for x in "$@"
para recorrer los valores puede considerarse más idiomático. La numeración también es bastante simple de agregar sin ninguna característica específica de shell -:
i=1
for x in "$@" ; do
echo "param $i is $x"
i=$((i+1))
done