Search code examples
bashcygwin

cygwin cp cannot stat file


I am trying to run the below script and copy the files with particular pattern of names from Source to working.

#!/bin/bash
(set -o igncr) 2>/dev/null && set -o igncr; # this comment is required
SOURCE="D:/backup/"
WORKING="D:/copyFromHere/"
Copy_Pattern="P0689\|P1391\|P0730"

for FILE in $(find "$SOURCE" `ls -Rl "$SOURCE" | egrep '^d' | awk '{print $9}'` -print 
2>/dev/null | grep "$COPY_PATTERN" |sed 's/_[0-9]\+//' | uniq);

do
cp -f "FILE" "$WORKING";

done;

i am running it on cygwin on windows.

But i am getting below error cp cannot stat file no such file or directory

Please help me figuring this out.

Thanks, Tom


Solution

  • May I make a slight recommendation:

    #!/bin/bash
    set -xv
    (set -o igncr) 2>/dev/null && set -o igncr; # this comment is required
    SOURCE="D:/backup/"
    WORKING="D:/copyFromHere/"
    Copy_Pattern="P0689\|P1391\|P0730"
    
    for FILE in $(find "$SOURCE" `ls -Rl "$SOURCE" | egrep '^d' | awk '{print $9}'` -print 2>/dev/null | grep "$COPY_PATTERN" |sed 's/_[0-9]\+//' | uniq);
    do
        echo "cp -f \"FILE\" \"$WORKING\"";
    done;
    set +xv
    

    The set -xv is a debugger for shell. It prints out the line being executed as written in your shell script, and then prints out the line after all variable interpolations have been made. This will let you see each set your program is taking, and where it might be having problems. The set +xv just turns off the debugging.

    I suspect that the problem is in cp -f "FILE" "$WORKING" line because the file FILE doesn't actually exist. I also suspect you're picking up file names (and copying fails there), and you may not be checking if directories actually exist before you copy files there. Use the set -o xv and you'll see a lot of these errors quite clearly.

    Putting your cp in an echo statement will also let you see what you're planning on executing before actually executing it. It's another way to help debug shell scripts.

    I also suspect your for loop might not be doing exactly what you want. It's an overly complex bad boy where you're executing two sub-shell commands at once. (Once using $(..) and another using back-ticks. I am vehemently against the use of for var in $(find ...) because of all sorts of issues. First, the find has to finish executing before the for loop can begin -- there's no parallel operation. Second, if there are funky file names, your for will simply fail. Third, it's very possible that find returns so many files, that your command buffer overflows and silently drops names of files without even letting you know it is happening. You're way better using:

     find ... | while read something
    

    It eliminates many of the issues that your for will run into.