bash脚本根据最终参数对每个参数执行操作

时间:2009-09-22 17:50:46

标签: bash arguments shift

假设您要创建一个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 个答案:

答案 0 :(得分:5)

/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

答案 1 :(得分:2)

您可以使用数组切片来消除最后一个参数:

tgt="${!#}"
for src in "${@:1:$#-1}"; do
    cp "$src" "$tgt"
done

答案 2 :(得分:1)

为什么呢? 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]}

我希望这会有所帮助。

答案 3 :(得分:1)

#!/bin/bash
tgt="${@: -1}"    # get the last parameter
for src in "$@"; do
    if [[ $src != $tgt ]]; then
        echo cp "$src" "$tgt"
    fi
done

答案 4 :(得分:0)

#!/bin/bash
t=(x "$@")
i=1; while [ $i -lt $# ]; do
  echo cp ${t[$i]} ${t[$#]}
  i=$(($i + 1))
done

答案 5 :(得分:0)

您不需要任何特定于bash的功能:

eval last=\${$#}
while [ $# -gt 1 ]; do
  echo "cp $1 $last"
  shift
done

答案 6 :(得分:0)

您可以直接执行此操作,而无需使用 xargs

编写脚本
echo source1 source2 | tr "\n" "\0" | tr " " "\0" | 
   xargs --verbose -0 -I{} cp {} dest

答案 7 :(得分:-1)

使用它来提取最后一个参数:

eval tgt = \ $$#

然后按照您的方式处理,当您点击$#时退出循环

这是whjole脚本:

eval tgt=\$$#

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

如果你问我就很简单!