скрипт bash для выполнения операции над каждым аргументом против последнего аргумента - PullRequest
0 голосов
/ 22 сентября 2009

Предположим, вы хотите создать скрипт bash, который не поддерживает никаких опций, но действует как cp, потому что cp, предоставляемый вашей системой, не принимает несколько источников.

Использование системы (гипотетической и неработающей) cp:

cp source target    # target may be a directory

Использование для скрипта будет:

cp.sh source... target    # target must be a directory

Вот отправная точка для сценария:

#!/bin/bash
tgt="$1"
shift
for src in "$@"; do
    echo cp $src $tgt
done

При запуске с аргументами "a b c d" (обратите внимание, что d является целью), он выдает:

cp b a
cp c a
cp d a

Цель состоит в том, чтобы исправить сценарий, чтобы выводить это вместо того, чтобы сохранить код простым:

cp a d
cp b d
cp c d

Ответы [ 8 ]

5 голосов
/ 22 сентября 2009

/ test.bash source1 source2 target1

#!/bin/bash

target=${!#} 

if [ ! -d $target ] ; then
    echo "$target must be a directory " >&2
    exit 1;
fi

args=("$@")
unset args[${#args[@]}-1]

for src in "${args[@]}"; do
    echo cp $src $target
done

выдаст

cp source1 target1
cp source2 target1
2 голосов
/ 23 сентября 2009

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

tgt="${!#}"
for src in "${@:1:$#-1}"; do
    cp "$src" "$tgt"
done
1 голос
/ 22 сентября 2009
#!/bin/bash
tgt="${@: -1}"    # get the last parameter
for src in "$@"; do
    if [[ $src != $tgt ]]; then
        echo cp "$src" "$tgt"
    fi
done
1 голос
/ 22 сентября 2009

Почему? Команда cp уже делает это. Сделайте man cp и вы увидите.

Если вы все еще настаиваете, вот два способа получить последний аргумент. Метод 1: поместите командную строку в массив и извлеките последний элемент:

arg=("$@")
last_arg=${arg[(($# - 1))]}

Первая строка помещает аргументы командной строки в массив arg. Если ваша командная строка содержит a b c d , тогда arg [0] == 'a', ... argv [3] == 'd'.

Вторая строка извлекает последний аргумент. (($ # - 1)) принимает количество аргументов (в данном случае 4), вычтите из него 1 (чтобы получить 3). Это выражение затем становится:

last_arg=${arg[3]}

, который указывает на последний аргумент.


Второй метод не очень переносим, ​​он использует переменную BASH_ARGV, которая равна $ @, но в обратном порядке. Если ваша командная строка a b c d , то $ {BASH_ARGV [0]} == 'd', ... $ {BASH_ARGV [3]} == 'a':

last_arg=${BASH_ARGV[0]}

Надеюсь, это поможет.

0 голосов
/ 25 сентября 2009

Вы можете сделать это напрямую без написания скрипта, используя xargs :

echo source1 source2 | tr "\n" "\0" | tr " " "\0" | 
   xargs --verbose -0 -I{} cp {} dest
0 голосов
/ 25 сентября 2009

Вам не нужны никакие специфичные для bash функции:

eval last=\${$#}
while [ $# -gt 1 ]; do
  echo "cp $1 $last"
  shift
done
0 голосов
/ 22 сентября 2009
#!/bin/bash
t=(x "$@")
i=1; while [ $i -lt $# ]; do
  echo cp ${t[$i]} ${t[$#]}
  i=$(($i + 1))
done
0 голосов
/ 22 сентября 2009

Используйте это, чтобы извлечь последний параметр:

eval tgt = \ $$ #

затем просто обработайте так же, как вы, а когда вы нажмете $ #, просто выйдите из цикла

Вот сценарий whjole:

eval tgt=\$$#

for src in $@
do
 if [ "$src" == "$tgt" ];
 then
    exit
fi
echo cp $src $tgt
done

Довольно просто, если вы спросите меня!

...