2009-09-22 4 views
0

시스템에서 제공하는 cp이 여러 소스를 허용하지 않기 때문에 cp처럼 작동하지만 옵션을 지원하지 않는 bash 스크립트를 작성한다고 가정합니다. 대한최종 인수에 대해 각 인수에 대해 연산을 수행하는 bash 스크립트

사용법 시스템의 (가상 깨진) 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 "[email protected]"; do 
    echo cp $src $tgt 
done 

인수가 "a b c d"인 경우 (tha

cp b a 
cp c a 
cp d a 

목적이 아닌 출력하는 스크립트를 수정하는 코드 간단하게 유지하면서 :

cp a d 
cp b d 
cp c d 

답변

5

/test.bash 소스 1 소스 2이 target1

#!/bin/bash 

target=${!#} 

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

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

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

출력됩니다

cp source1 target1 
cp source2 target1 
+0

나는 이것을 정말로 좋아합니다! $ target과 $ src (공백이있는 경로를 지원하기 위해)를 사용하는 것에 대해 따옴표를 추가하고 있지만, 그렇지 않으면 거의 완벽합니다. –

+0

'for [-f "$ src"]'(또는'-a')를'for' 루프 안에 추가해야합니다. –

1

왜 t d, 그것을 출력하는) 타겟인가? cp 명령은 이미이를 수행합니다. 남성 cp을 수행하면 확인할 수 있습니다.

여전히 주장하는 경우 마지막 인수를 얻는 방법은 두 가지가 있습니다. 방법 1 : 배열에 명령 줄을 배치하고 마지막 요소를 추출하십시오.

arg=("[email protected]") 
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]} 

도움이 되었기를 바랍니다. #

루프

을 다음 당신은 같은 방법으로 처리하고 $ #을 쳤을 때 바로 종료 $$

가 여기

평가 TGT = \

+0

이미이 동작을 지원합니다. 그러나 나는 실행하지 않는 다른 프로그램을 가지고있다. –

-1

사용이 마지막 매개 변수를 추출 whjole 대본 :

나 한테 물으면 아주 간단 해!

+0

이 방법은 내 손을 이긴다. 너 한테 모자라. –

+0

$ #에 도달했을 때 멈추는 부분은 추가적으로 루프 인덱스를 추적해야하는데, 신경 쓰지 않아도됩니다. 그리고 다른 답변 중 일부는 "eval"은 필요하지 않습니다. –

+0

색인이 필요 없다면 현재 값을 tgt와 비교하십시오. $ #을 치면 종료하는 것은 $ #의 값을 치는 것을 의미합니다. – ennuikiller

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

'$ *'을 사용하지 마십시오; 인수 내에서 공백을 보존하지 않습니다 (추가 인수가 생성됩니다). ''$ @ ''- 거의 항상 사용하십시오. –

+0

사실, 나는 항상 "$ @"를 사용하여 명령을 묶을 때, 왜 여기에서하지 않았는지 확신하지 못했습니다 ... – DigitalRoss

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

나쁘지는 않지만 사용 된 비교를 통해 마지막 인수를 제거하는 "unset"방법을 선호합니다 여기 (소스가이 코드로 목표와 실제로 동일하면 어떻게되는지 상상해보십시오). –

+0

하지만 너는 듣고 싶지 않을거야. 그렇지? "cp :'d '와'd'는 같은 파일입니다." –

+0

또는 "cp : 디렉토리'd '를 생략합니다." –

2

당신은 인수의 마지막을 떠나 슬라이스 배열을 사용할 수 있습니다

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

당신은 어떤 bash는 특정 기능이 필요하지 않습니다

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

300 번째 인수 (300 개의 인수가있는 경우)에서 300 달러를 사용합니다. 모든 본 셸에서 작동하지 않습니다 (예 : Solaris 10/bin/sh :'set-abcdefghijkl; echo $ 10'은 Korn 쉘에 대해서도 마찬가지입니다 (Solaris 10에서도 마찬가지입니다) –

+0

'a0'을 생성합니다. –

+0

물론 $ #> 9의 경우 $ {N}을 사용해야합니다 (예 : $ {10}, $ {300}). ksh, bash,/bin/sh를 사용하면 Solaris 10에서 제대로 작동합니다. – Idelic

0

당신은 xargs를 사용하여 스크립트 작성하지 않고 직접이 작업을 수행 할 수 있습니다 물론 "CP"의

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