2011-11-16 2 views
1

이 스크립트를 사용하여 새 .bin 파일을 다운로드 할 폴더를 모니터링하고 있습니다. 그러나, 그것은 작동하지 않는 것 같습니다. grep을 제거하면 Downloads 폴더에 생성 된 파일을 복사 할 수 있지만 grep은 작동하지 않습니다. 문제가 두 값을 비교하는 방법 인 것 같지만 실제로 어떻게해야할지 모르겠습니다.새 파일의 폴더를 모니터링하는 작은 스크립트에서 스크립트가 잘못된 파일을 찾는 것 같습니다

#!/bin/sh 

downloadDir="$HOME/Downloads/" 
mbedDir="/media/mbed" 

inotifywait -m --format %f -e create $downloadDir -q | \ 
while read line; do 
    if [ $(ls $downloadDir -a1 | grep '[^.].*bin' | head -1) == $line ]; then 
     cp "$downloadDir/$line" "$mbedDir/$line" 
    fi 
done 
+0

나는 무엇을해야할지 명확하지 않습니다. 비교 목적은 무엇입니까? 작성된 것처럼 파일이 "bin"을 포함하는 첫 번째 (알파벳 순으로) 파일 인 경우에만 파일을 복사하는 것으로 보입니다 (grep 패턴이 줄 끝 부분에 고정되어 있지 않으므로 "bin"으로 끝나지 않아도됩니다). –

+1

2. 물건, 1. 항상 "$ line"과 같이 db-quotes로 알려지지 않은 자연 변수를 둘러 쌉니다. '$ line'에 값의 공백이 생겨 물건을 부러 뜨릴 수있는 경우 2. 셸 디버깅, 즉'set -vx'를 while 루프 위에 놓습니다. 그런 다음 각 줄/코드 블록을보고 각 변수에 할당 된 값을 볼 수 있습니다. 그렇다면 이것이 어디에서 실패하고 있는지 쉽게 알 수 있습니다. 알아낼 수 없다면, 게시물을 수정하여 디버깅 출력을 다시 포함 시키십시오. 행운을 빕니다. – shellter

+0

@GordonDavisson 비교의 목적은 정규 표현식을 앵커하는 것을 잊었을지라도 특정 정규 표현식과 일치하는 파일 만 이동하는 것입니다. 나는 inotify가 패턴과 일치하는 것을 움직이는 방법을 볼 수 없었다. – Squidly

답변

2

ls $downloadDir -a1 | grep '[^.].*bin' | head -1은이 문제를 해결하는 잘못된 방법입니다. 이유를 보려면 다운로드 디렉토리에 a.txtb.bin이라는 파일이 있고 그 다음 c.bin이 추가되었다고 가정합니다. inotifywaitc.bin, lsa.txt\nb.bin\nc.bin이 (실제 줄 바꿈하지 \ N과), grepb.bin\nc.bin에, headc.bin과 일치하지 않을 b.bin를 떠나 첫 번째 줄, 남기고 모두 얇은 제거 할 것이라고 인쇄 할 인쇄 할 것이다. 디렉토리 목록을 스캔하지 않고 .bin으로 끝나는 지 확인하려면 $line을 확인해야합니다. 나는 당신이 할 수있는 세 가지 방법으로주지 : $line을 확인 그렙 사용

첫 번째 옵션을,하지 목록 : 나는 GREP의 출력이 표시되지 않도록 -q 옵션을 사용하고

if echo "$line" | grep -q '[.]bin$'; then 

참고하고, if 명령에 종료 상태를 확인시키는 것 (일치하는 항목을 찾은 경우 성공, 그렇지 않은 경우 실패)을 지정하는 것입니다. 또한 RE는 줄 끝 부분에 고정되어 있으며 마침표는 괄호 안에 있으므로 실제 기간과 일치합니다 (일반적으로 정규 표현식에서 .은 단일 문자와 일치합니다). \.bin$도 여기에서 작동합니다. 그것은이 있는지

if [ "${line%.bin}" != "$line" ]; then 

"${line%.bin}" 부분은 끝에서 손질 .bin와 $ 라인의 값을 제공 :

두 번째 옵션은 $line.bin 끝나는 있는지 확인하기 위해 변수 내용을 편집 할 수있는 쉘의 능력을 사용합니다. 이것이 $line과 같지 않다면 $line.bin으로 끝나야합니다.

세 번째 옵션을 사용 강타의 [[ ]] 표현이 직접 패턴 매칭을 할 :

if [[ "$line" == *.bin ]]; then 

이것은 단지 bash는 작동 간단하고 무리의 깨끗한하지만 (IMHO) (당신은 스크립트를 즉 시작해야합니다 #!/bin/bash).

기타 참고 사항 : 파일 이름에 공백과 백 슬래시와 관련된 몇 가지 문제를 피하려면 while IFS= read -r line; do을 사용하고 @ shellter의 이중 따옴표 권장 사항을 신중하게 따르십시오.

나는 또한 inotifywait에 익숙하지 않지만 AIUI의 -e create 옵션은 파일이 만들어 질 때 알려주며 그 내용이 완전히 쓰여 졌을 때 알려주지 않습니다. 타이밍에 따라 부분적으로 작성된 파일을 복사 할 수 있습니다.

마지막으로 중복 된 파일 이름을 확인할 필요가 없습니다. foo.bin 파일을 다운로드하면 복사되고 원본을 삭제 한 다음 foo.bin이라는 다른 파일을 다운로드하면 어떻게됩니까? 스크립트가 지금은 그대로 자동으로 첫 번째 foo.bin을 덮어 씁니다.원하는 내용이 아닌 경우 다음을 추가해야합니다.

if [ ! -e "$mbedDir/$line" ]; then 
    cp "$downloadDir/$line" "$mbedDir/$line" 
elif ! cmp -s "$downloadDir/$line" "$mbedDir/$line"; then 
    echo "Eeek, a duplicate filename!" >&2 
    # or possibly something more constructive than that... 
fi