linuxbashgnu-findutils

Find command works in terminal but not in bash script


I wrote a find command, which finds the files, but excludes other files/directories. I did echo this code and copied it. If I paste it in the terminal, it works. Some files were excluded. But if I execute it from the script, it does not work as expected.

I tried to escape my variables, quote them, between brackets like $() or ${} but nothing worked.

My find code looks like this:

find ${StartDirs[*]} $pat -print

In fact it will be executed like:

find ./bin  -wholename './bin/backup2' -prune -o -wholename './bin/backup3' -prune -o -print

The second code above works in the terminal but not in the script. What did I do wrong?

For more info I will try to paste necessary code below I am trying to make a backup and want to do that with find and cp. Most code of my script are omitted. I think the code below is the necessary minimal code for this problem.

StartDirs=();
ExcludedFiles=(); #files/directories which needs to be excluded

#check and store excluded files
CheckExcludedFile(){ #this function will be called over and over again by another function (getopts). It depends on the chain of -x options. With the -x option I can decide which file i want to exclude. The Getopts function is also omitted.

    exclFile=`find $1 2>/dev/null | wc -l` 
    if [ $exclFile -lt 1 ]; then
        echo $FILEMAPNOTEXIST | sed 's~-~'$1'~g' # FILEMAPNOTEXIST is a variable from another script with error messages
        exit 0
    else
        ExcludedFiles+=($1) #add excluded file/dir path to array
    fi
}

MakeBackup(){
        for i in ${ExcludedFiles[*]}
        do
            s=" -wholename $i -prune -o"
            pat=$pat$s
        done
        # the code above edits the array elements of the EcludedFIles[]
        #For example by calling the script with the -x option (-x fileA -x fileB -x fileC) wordt als volgt: -wholename 'fileA' -prune -o -wholename 'fileB' -prune -o -wholename 'fileC' -prune -o.
        #the pat variable will be used for the find command to ignore files/directories

    mkdir -p ~/var

    echo "Start-time $(date '+%F %T')" >> ~/var/dq.log  

    find ./bin  -wholename './bin/backup2' -prune -o -wholename './bin/backup3' -prune -o -print
    #the code above should work like in terminal. That is not the case..

    # find ${StartDirs[*]} $pat -print #this should work also.

    # cp -av ${StartDirs[@]} $Destination >> ~/var/dq.log find command not working therefore this rule is commented

    echo "end-time $(date '+%F %T')" >> ~/var/dq.log
}

The expected result should simply be some files/directories being excluded if given.

If a full script is necessary, let me know.


Solution

  • The command find ./bin -wholename './bin/backup2' -prune -o -wholename './bin/backup3' -prune -o -print should work as intended, provided the current directory is directly above bin/. This may be the cause of your problems: If in the real script you assemble path names which do not match the prefixes in the found paths then e.g. the prune will not work. Example: You have a dir /home/me; in it is bin/backup2/, bin/backup3/ and stuff-to-backup/. Now if you are in /home/me and execute find . it finds e.g. ./bin/backup2 which will be pruned.

    But if you put this in a script and call the script with path arguments, e.g. /home/me, it will find the same files but the paths will be different, e.g. /home/me/bin/backup2, and will not prune it because it does not match the supplied exclude pattern, even though they are the same files. Likewise no patterns supplied with -wholename will be found. Here is a question which addresses this problem.