2012-04-19 4 views
0

나는 현재 디렉토리와 모든 하위 direcotires를 이동하고를 heres .SQL모호한 재

의 코드

HEADER="--SQL HEADER" 

for f in 'find . -name *.sql'; 
do 
     echo $f 
     echo -e $HEADER > $f.tmp; 
     FNAME=${f//\//_/}; 
     echo -e "\n\n--MORE ANNOTATIONS ${FNAME%.*}:1" >> $f.tmp; 
     cat $f >> $f.tmp; 
     mv $f.tmp $f; 
     rm $f.tmp 
done; 

메신저 A의 조각을 종료 각 파일에 약간의 주석을 추가하기 위해 노력하고있어 배쉬에서 초보자 그래서 몇 가지 오류를 생각 내가 얻을 루프 로 찾기 문으로 인해 수 있습니다 받고 있지만, 이것은 오류가 메신저

find . -name X.sql A.sql W.sql E.sql S.sql 
./annotate.sh: line 6: $f.tmp: ambiguous redirect 
./annotate.sh: line 8: $f.tmp: ambiguous redirect 
./annotate.sh: line 9: $f.tmp: ambiguous redirect 
mv: invalid option -- n 
Try `mv --help' for more information. 
rm: invalid option -- n 
Try `rm --help' for more information. 

어떤 도움이 크게 될 것 apprec =)

답변

3

여기에 문제가 있습니다. 귀하의 "에코"를 범 :

echo $f 

출력

find . -name X.sql A.sql W.sql E.sql S.sql 

나는 문제는 find 명령에서 직선 작은 따옴표 ('')가 생각 대신 역 인용 부호의 (``). 그래서 실제로는 찾기를 실행하지 않고 단순히 와일드 카드를 확장합니다.

이 찾아 전달하는 대신 쉘에 의해 평가됩니다, 그래서 당신은 와일드 카드를 인용 할 수 있습니다 :

for f in `find . -name \*.sql`; 

그러나 사용하려는 경우 해결해야 스크립트에 몇 가지 문제가있다 그것은 한 번 이상. ormaaj's answer을 참조하십시오.

+5

+1 그리고 혼란을 피하기 (그리고 보너스로 중첩 가능)는'$ (명령) 대신 역 따옴표 변형의'양식을 사용하는 것이 좋습니다하기 위해 '\'명령 \ ''. –

+1

좋지 않다 ...'for '와 backticks를 사용하여 파일을 반복하는 것을 권장하지 않는다. ('$()'). 가장 즉각적인 문제를 지적했기 때문에 -1이 아닙니다. – ormaaj

+0

정확하고이를 지적 해 주셔서 감사합니다.쉘 스크립트를 작성하는 방법을 가르치 려하지 않고 단순히 질문에 대답하고있었습니다. – theglauber

2

이미 지적했듯이 문제는 find가 실제로 실행되고 있지 않다는 것입니다. 그러나이 패턴은 매우 잘못되었습니다. 결과를 단어로 분할하는 것은 단어 분할을 필요로하기 때문에 명령 치환으로 일어나는 일들에 대해 for 루프를 사용하는 것은 반복하지 않는다. 파일명에 개행 문자를 포함 할 수 있기 때문에 경로명 확장을 사용할 수없는 경우에도 문제가된다.

-exec을 사용하는 것이 좋습니다.

find . -name '*.sql' -exec scriptname {} + 

또는, (이 배쉬의 최신 버전입니다 가정), globstar를 사용없이 find (:

#!/usr/bin/env bash 
header="--SQL HEADER" 

for f in "[email protected]"; do 
    echo "$f" >&2 
    fname=${f//\//_/} 

    cat - "$f" <<EOF >"$f.tmp" 
    ${header}$'\n\n' 
    --MORE ANNOTATIONS ${fname%.*}:1 
    EOF 

    mv "$f.tmp" "$f" 
done 

는 다음과 같은 find을 실행 : 먼저 파일 chmod u+x scriptname이 스크립트를 작성 원하는 경우 ksh도 비슷한 기능을 제공합니다.) 이것은 작업에 따라 느려질 수 있습니다 - 쉘은 파일 목록을 미리 생성해야합니다. 배시 넷이 있고 경우

#!/usr/bin/env bash 
shopt -s globstar 

for f in ./**/*.sql; do 
    ... 

또는 필요한 GNU 유틸리티와 시스템은 -print0를 사용합니다.

find . -name '*.sql' -print0 | while IFS= read -rd '' f; do 
    # <body of the above for loop here> 
done 

참조 : http://mywiki.wooledge.org/UsingFind