Как использовать значения параметров внутри цикла for

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

0
26.02.2018, 09:38
2 ответа

El problema con $($(echo $z))es que se expande, primero a$(1)(si $zes 1 )y luego el shell intenta ejecutar 1como 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
4
28.01.2020, 02:16
for z in 1..$(seq 1 $#);

Eso se expandiría a 1..1, 2, 3para tres parámetros. seqya imprime los números como palabras distintas, y forrealmente 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 varcontiene 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
1
28.01.2020, 02:16

Теги

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