linux - Use 'find' to find and delete large files of a certain type

06
2014-04
  • Pred

    I am trying to find and rm -rf large files in RHEL, but what I would expect from this command that would give me purely the file directories, feeding them into rm -rf, it is not removing them. My FU might be off, so please review this line, I thought it would work.

    find /tmp -type f -size +50000k -exec ls -lh {} \; | awk '{ print $9 }' | rm -rf
    
  • Answers
  • user49740

    You can use find /tmp -type f -size +50000k -delete instead, which is clearer, simpler and more efficient.


  • Related Question

    linux - find with exec : how to perform multistep conditional action on each file
  • Sudhi

    I have bunch of php files in directory structure say /mylibs
    I want to run a simple php -l $file on each php file which checks for syntax errors

    find /mylibs -type f -iname "*.php" -exec php -l {} &>/dev/null \;
    

    thats step one, the &>/dev/null eats verbose output from php (found syntax errors or not)

    The php -l returns 0 if no error is found depending upon which, I want to copy them to some other dir say /mybin. To check if this works as expected I tried

    find /mylibs -type f -iname "*.php" -ok php -l {} &>/dev/null ; echo $? \;
    

    but this simply prints 1 on the terminal and does not ask for confirmation (-ok acts same as -exec after interactive confirmation)

    What am I doing wrong here ? is it not possible to do this?


  • Related Answers
  • grawity

    ; is the shell's command separator. Everything after it will be a separate command and won't be passed to find, since command parsing is done before execution. Likewise, &>/dev/null applies to the entire find command, not just to php, regardless of where it is located (before, in the middle, or after).

    To use such operators in your -exec or -ok, you will have to explicitly call a shell:

    find ... -exec bash -c 'php -l "{}" >&/dev/null; echo $?' \;
    

    Note that the special characters are inside quotes, which means they will be passed literally to find and then to bash.

    This is less simple but might be more reliable with "weird" filenames:

    find ... -exec bash -c 'php -l "$1" >&/dev/null; echo $?' -- {} \;
    

    This will display the results in a more readable form: (this is entirely about bash scripting now, not about find anymore)

    find ... -exec bash -c '
        if php -l "$1" >&/dev/null; then
            echo "$1: pass"
        else
            echo "$1: fail"
        fi' -- {} \;
    
  • Jon Zobrist

    I would save your found files to an array, and run your php -l on each item in a for or while loop, with an if [ "$?" != "0" ] as a step.

    find /mylibs -type f -iname "*.php" -exec php -l {} &>/dev/null \;
    

    I would change to

    MYFILES=$(find /mylibs -type f -iname "*.php")
    SAVEIFS=$IFS
    
    IFS=$(echo -en "\n\b")
    for FILE in ${MYFILES}
    do
      php -l ${FILE} 2&>1 >>/dev/null
      if [ "$?" != "0" ]
        then
          echo "ERROR on ${FILE}
      else
          /bin/cp ${FILE} ${NEWPATH}
      fi
    done
    IFS=$SAVEIFS