1

I am currently writing a bash script with find in order to delete all kinds of files and folders. The script looks as follows:

#!/bin/bash
# managed by puppet
echo "INFO: Starting ${0}"
# Setting parameters
while getopts "l:d:f:t:'" option
  do
    case "${option}"
    in
    l) log=${OPTARG} ;;
    d) directory=${OPTARG} ;;
    f) find_command=${OPTARG} ;;
    t) truncate=1 ;;
    *) echo "ERROR: Wrong Option defined" ; exit 101 ;;
  esac
done
if ! [ -d "/var/log/sbp_logs" ] ; then
 mkdir /var/log/sbp_logs
fi
date=$(date +%Y-%m-%d)
# Deleting of files
  echo "INFO: Starting the deletion of files"
if [[ ${truncate} -eq 1 ]] ; then
  find ${directory} ${find_command} -exec truncate -s0 {} \;
else
  find ${directory} -mindepth 1 ${find_command} -print >> /var/log/sbp_logs/${log}_${date}.log 2>&1
fi
echo "INFO: Finished"

The truncate part can be ignored for now, as I only have two cases where I have to use it, and that part works for me. I also removed the rm -f part, as I want to make sure, that the correct files will be deleted first.

I execute the script as follows:

/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log/ -f '-ctime +5 -type f ( -name '*err*' )' -l 'test'

I get the expected result when I do cat on the log file which the script created:

cat 2022-04-03_test.log
/xx/xx/xx/xx/log/x.err
/xx/xx/xx/xx/log/x.err
/xx/xx/xx/xx/log/x.err
/xx/xx/xx/xx/log/x.err

When I execute the exact same command, only with a different path and -name pattern on a different Server, I get the following:

/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log -f '-ctime +5 -type f ( -name '*log*' )' -l 'test'

cat test_2022-04-04.log
find: paths must precede expression: 2022-04-01_server_logs_ID16.txt
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

I don't know what the issue is, because both servers are similar systemwise.

What I discovered was, that on the second server, the find searches in the current directory I am in for *log* and then replaces the -name pattern with the result, but I don't know why, because I am using quotes around the pattern.

I also tried several quotings, like:

/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log -f "-ctime +5 -type f -name '*log*'" -l 'test'
/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log -f "-ctime +5 -type f \( -name '*log*' \)" -l 'test'
/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log -f '-ctime +5 -type f \( -name "*log*" \)' -l 'test'
/usr/local/bin/archive_sbp_logs_script.sh -d /xx/xx/xx/xx/log -f '-ctime +5 -type f -name "*log*"' -l 'test'

Without any result.

I compared the Kernel version and find version, which is the same on both servers:

find --version
find (GNU findutils) 4.5.11

hostnamectl
Kernel: Linux 3.10.0-1160.53.1.el7.x86_64

As the script is being rolled out through puppet, I checked, if these are the same scripts with sha256sum archive_sbp_logs_script.sh with the same result on both Servers.

jonrsharpe
  • 107,083
  • 22
  • 201
  • 376
Ch0p
  • 21
  • 1
  • 6
  • 1
    You can't store the command arguments in a single string. In your first test-case, `find ${find_command}` is equivalent to type `find -ctime +5 -type f -name \'*log*\'\"`, which, even in the lucky case that the glob doesn't expand, won't find the files that you want. – Fravadona Apr 04 '22 at 11:52
  • See [How to store a command in a variable in Linux?](https://stackoverflow.com/q/5615717/4154375) and [BashFAQ/050 (I'm trying to put a command in a variable, but the complex cases always fail!)](https://mywiki.wooledge.org/BashFAQ/050). They are relevant here because you are trying to store part of a command in a variable. – pjh Apr 04 '22 at 12:03

0 Answers0