Home > OS >  Bash find command : No such file or directory
Bash find command : No such file or directory

Time:01-17

This one is stumping me quite well! Big points for a resolution!

I need to traverse a directory and all levels below it to discover any files or directories that do not match a pattern.

I'm using find command -

find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '/home/user/inbox/*' -a ! -path /home/user/inbox/imaging -a ! -path '/home/user/inbox/imaging/*' \) -ls

The error -

find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '/home/user/inbox/*' -a ! -path /home/user/inbox/imaging -a ! -path '/home/user/inbox/imaging/*' \) -ls: No such file or directory

Yes, each of those directories in the find command do indeed exist -

ls -ld /home/user/inbox /home/user/inbox/imaging/
drwxr-xr-x. 5 user grp-ftp-admin 8192 Jan 13 12:45 /home/user/inbox
drwxr-xr-x. 3 user grp-ftp-admin  152 Jan 13 12:21 /home/user/inbox/imaging/

The entire script source -

#!/usr/bin/env bash

function findInvalidArtifacts() {
    unset   inbox sshCommand exitCode cmdOutput
    s ilocal    -A VENDOR=(
                ['FTPBASE']="/home/user"
                ['FTPSOURCEDIR']="/home/user/inbox/imaging"
                ['FRIENDLYNAME']="user"
                ['ENVIRONMENT']="dev"
            )

    inbox="${VENDOR['FTPBASE']}/inbox"
    printf -v sshCommand "find -L %s \( ! -path %s -a ! -path '%s/*' -a ! -path %s -a ! -path '%s/*' \) -ls" \
        "${inbox}" "${inbox}" "${inbox}" "${VENDOR['FTPSOURCEDIR']}" "${VENDOR['FTPSOURCEDIR']}"
    #cmdOutput=$(ssh ${SSHOPTIONS} ${SSHUSERHOST} "${sshCommand}" 2>&1)
    cmdOutput=$("${sshCommand}")
    exitCode="${?}"
    if (( 0 != $exitCode )); then
        printf "FAILED - sshCommand=[%s], exitCode=[%d], cmdOutput=[%s]\n" "${sshCommand}" "${exitCode}" "${cmdOutput}"
        exit 1
    fi
    printf "SUCCEEDED - sshCommand=[%s] exitCode=[%d]\n" "${sshCommand}" "${exitCode}"
    printf "%s\n\n" "${cmdOutput}"
} # end findInvalidArtifacts()

And, finally, running the script with bash -vx -

#!/usr/bin/env bash

function findInvalidArtifacts() {
        unset   inbox sshCommand exitCode cmdOutput
        local   -A VENDOR=(
                                ['FTPBASE']="/home/user"
                                ['FTPSOURCEDIR']="/home/user/inbox/imaging"
                                ['FRIENDLYNAME']="user"
                                ['ENVIRONMENT']="dev"
                        )

        inbox="${VENDOR['FTPBASE']}/inbox"
        printf -v sshCommand "find -L %s \( ! -path %s -a ! -path '%s/*' -a ! -path %s -a ! -path '%s/*' \) -ls" \
                "${inbox}" "${inbox}" "${inbox}" "${VENDOR['FTPSOURCEDIR']}" "${VENDOR['FTPSOURCEDIR']}"
        #cmdOutput=$(ssh ${SSHOPTIONS} ${SSHUSERHOST} "${sshCommand}" 2>&1)
        cmdOutput=$("${sshCommand}")
        exitCode="${?}"
        if (( 0 != $exitCode )); then
                printf "FAILED - sshCommand=[%s], exitCode=[%d], cmdOutput=[%s]\n" "${sshCommand}" "${exitCode}" "${cmdOutput}"
                exit 1
        fi
        printf "SUCCEEDED - sshCommand=[%s] exitCode=[%d]\n" "${sshCommand}" "${exitCode}"
        printf "%s\n\n" "${cmdOutput}"
} # end findInvalidArtifacts()

findInvalidArtifacts
  findInvalidArtifacts
  unset inbox sshCommand exitCode cmdOutput
  VENDOR=(['FTPBASE']="/home/user" ['FTPSOURCEDIR']="/home/user/inbox/imaging" ['FRIENDLYNAME']="user" ['ENVIRONMENT']="dev")
  local -A VENDOR
  inbox=/home/user/inbox
  printf -v sshCommand 'find -L %s \( ! -path %s -a ! -path '\''%s/*'\'' -a ! -path %s -a ! -path '\''%s/*'\'' \) -ls' /home/user/inbox /home/user/inbox /home/user/inbox /home/user/inbox/imaging /home/user/inbox/imaging
   'find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '\''/home/user/inbox/*'\'' -a ! -path /home/user/inbox/imaging -a ! -path '\''/home/user/inbox/imaging/*'\'' \) -ls'
./try.sh: line 16: find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '/home/user/inbox/*' -a ! -path /home/user/inbox/imaging -a ! -path '/home/user/inbox/imaging/*' \) -ls: No such file or directory
  cmdOutput=
  exitCode=127
  ((  0 != 127  ))
  printf 'FAILED - sshCommand=[%s], exitCode=[%d], cmdOutput=[%s]\n' 'find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '\''/home/user/inbox/*'\'' -a ! -path /home/user/inbox/imaging -a ! -path '\''/home/user/inbox/imaging/*'\'' \) -ls' 127 ''
FAILED - sshCommand=[find -L /home/user/inbox \( ! -path /home/user/inbox -a ! -path '/home/user/inbox/*' -a ! -path /home/user/inbox/imaging -a ! -path '/home/user/inbox/imaging/*' \) -ls], exitCode=[127], cmdOutput=[]
  exit 1

This is a stumper. I cannot see where why find is complaining about 'no such file or directory'.

Appreciate the valiant effort, however the constructed command still does not return the desired results. The contents of finding all existing artifacts in /home/user/inbox are:

    /home/user/inbox
    /home/user/inbox/invalidDir2
    /home/user/inbox/invalidDir2/invalidSubdir2
    /home/user/inbox/invalidDir2/invalidSubdir2/invalidFile1
    /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2
    /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2/invalidSubSubSubDir2
        /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2/invalidSubSubSubDir2/invalidSubSubSubSubDir2
        /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2/invalidSubSubSubDir2/invalidSubSubSubSubDir2/invalidFile
        /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2/invalidSubSubSubDir2/invalidFile
        /home/user/inbox/invalidDir2/invalidSubdir2/invalidSubSubDir2/invalidFile
    /home/user/inbox/imaging
    /home/user/inbox/imaging/validFile
    /home/user/inbox/imaging/invalidFile
    /home/user/inbox/imaging/invalidImagingDir1
    /home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1
    /home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1/invalidFile1
/home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1/invalidSubSubDir1
/home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1/invalidSubSubDir1/invalidSubSubSubDir1
/home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1/invalidSubSubDir1/invalidSubSubSubDir1/invalidFile
/home/user/inbox/imaging/invalidImagingDir1/invalidSubdir1/invalidSubSubDir1/invalidFile
    /home/user/inbox/imaging/invalidImagingDir1/invalildFile
    /home/user/inbox/invalidFile
    /home/user/inbox/invalidDir1
    /home/user/inbox/invalidDir1/invalidSubdir1
    /home/user/inbox/invalidDir1/invalidSubdir1/invalidFile1
    /home/user/inbox/invalidDir1/invalidSubdir1/invalidSubSubDir1
/home/user/inbox/invalidDir1/invalidSubdir1/invalidSubSubDir1/invalidSubSubSubDir1
/home/user/inbox/invalidDir1/invalidSubdir1/invalidSubSubDir1/invalidSubSubSubDir1/invalidFile
/home/user/inbox/invalidDir1/invalidSubdir1/invalidSubSubDir1/invalidFile

The result set should NOT contain anything matching the directory to search in, or any of the parameters passed to your function that constructs the command. Results should NOT contain these lines -

    /home/user/inbox
    /home/user/inbox/imaging
    /home/user/inbox/imaging/validFile

The command your function constructs looks like this -

find -L /home/user/inbox '(' '!' -path /home/user/inbox -a '!' -path '/home/user/inbox/*' -a '!' -path /home/user/inbox/imaging -a '!' -path '/home/user/inbox/imaging/*' ')' -ls

which returns nothing at all

I'm beginning to think that the find command is not what I need to obtain the desired results and that I'll need to do some more processing of the result set to disclude, probably awk or something.

CodePudding user response:

Relevant snippet:

printf -v sshCommand "find -L %s \( ! -path %s -a ! -path '%s/*' -a ! -path %s -a ! -path '%s/*' \) -ls" [more args]
cmdOutput=$("${sshCommand}")

This is a classic pitfall of trying to shove a command into a variable and run it. The basic solution is to use a function, not a variable.

The reason for your error is that Bash determines the name of the command you're trying to run by selecting the first word of the command line after completing all of its parsing steps. You want to use the command find with some arguments, but since you have "${sshCommand}" in quotes, there's only one word in the entire command line so Bash thinks the command you want is called find -L /home/dir ( ! -path etc etc... ). I bet you don't have any executables with that name on your system.

A function equivalent of what you're trying to do might look like:

_findCmd() {
  searchDir=$1 # first arg is the directory to search from
  shift
  
  # each extra argument is a directory to exclude from the search
  # we can loop over the list and build the arguments that find needs
  # in an array
  path_args=()
  if (( $# > 0 )) ; then
    path_args =( "(" "!" "-path" "$1" )
    shift
    while (( $# > 0 )) ; do 
      path_args =( "-a" "!" "-path" "$1" )
      shift
    done
    path_args =( ")" )
  fi
  find -L "$searchDir" "${path_args[@]}" -ls
} 

cmdOutput=$( _findCmd /home/user/inbox /home/user/inbox "/home/user/inbox/*" /home/user/inbox/imaging "/home/user/inbox/imaging/*" )

CodePudding user response:

Putting aside the correct escaping of ssh remote commands, here's a remark about your find command

find -L /home/user/inbox ! -path '/home/user/inbox/*'

Excludes any path that starts with /home/user/inbox/ (leaving only one possible match which is /home/user/inbox).

Also, for excluding /home/user/inbox/imaging/validFile while including /home/user/inbox/imaging/invalidFile, using ! -path '/home/user/inbox/imaging/*' is wrong, for the same reason as above.

  • Related