Linux Bash - 使用find命令排除目录

3
我正在编写一个bash脚本,遇到了一些问题,并且已经确定出有问题的代码。
使用变量作为参数时,find命令不能排除目录。
现在我需要把“-not -path ./dir”这个参数赋值给一个变量,在循环中使用,但是如果我这样做,它似乎不起作用。
我在下面列出了可以产生期望输出的命令以及我的版本,目前我的版本存在问题。请参见下面的测试:

变量赋值

findIgnorePaths="-not -path ./\.git\* -not -path ./administrator/cache\* -not -path ./images\* -not -path ./logs\* -not -path ./cache\* -not -path ./media\* -not -path ./plugins\* -not -path ./tmp\*"

期望的输出。

find ./ -type d -not -path ./\.git\* -not -path ./administrator/cache\* -not -path ./images\* -not -path ./logs\* -not -path ./cache\* -not -path ./media\* -not -path ./plugins\* -not -path ./tmp\*

输出故障

find ./ -type d ${findIgnorePaths}

如果有人想要查看我正在进行的脚本,其中上述问题存在,请看下面:

原始脚本(不需要阅读以回答问题,但是...提供给那些好奇的灵魂)

#!/bin/sh

declare -a ignoreDirs=()
findIgnorePaths=""
seperator="\e[33m**********************************\e[0m\n"

clear
printf "\n\n"

if [[ "${PWD##*/}" != "public_html" ]]
then
    printf "\e[31mThis script will not run unless current location is; /home/*/public_html/*\e[0m\n"
    exit
fi

echo "Site Locker! This will change all directory permissions to 555. And all file permissions to 444. Read only accces."

echo #Move to new line
echo "Are you sure you want to make changes to files/directories within the below location?"
printf "$seperator"
printf "\e[0;49;96m${PWD##/home/}\e[0m\n"
printf "$seperator"
echo #Move to new line

read -r -p "Y/n " response
echo #Move to new line
if [[ $response =~ ^([nN][oO]|[nN])$ ]]
then
    printf "\n\e[31mNo changes made. Quitting.\e[0m\n\n"
    exit
fi

printf "\e[95mIf you're working with a Joomla site, please select\nthe **JOOMLA** preset in the list below.\e[0m\n\nPlease select directory #) to add to the ignore list:\n\e[92m"

currentDir=( "**SAVE/SKIP**" "**JOOMLA**" )
currentDir+=( $(find . -maxdepth 1 -type d) )
select DIR in ${currentDir[@]};
do
  case $DIR in
        *SAVE*)
          printf "\n\n\e[92mDone!!\e[0m\n\n"
          break
          ;;
        *JOOMLA*)
          printf "\n\e[92mApplying Joomla preset.\n"
          ignoreDirs+=("./.git" "./administrator/cache" "./cache" "./images" "./logs" "./media" "./tmp" "./plugins")
          findIgnorePaths+=" -not -path ./\.git\* -not -path ./administrator/cache\* -not -path ./images\* -not -path ./logs\* -not -path ./cache\* -not -path ./media\* -not -path ./plugins\* -not -path ./tmp\*"
          printf "\n\n\e[31mIgnore list:\n"
          for item in "${ignoreDirs[@]}"
          do
              printf "$item\n"
          done
          ;;
        *)
          ignoreDirs+=("$DIR")
          findIgnorePaths+=" -not -path ${DIR}\*"
          printf "\n\n\e[31mIgnore list:\n"
          for item in "${ignoreDirs[@]}"
          do
              printf "$item\n"
          done
          printf "\e[92m"
          ;;
  esac
done
findIgnorePaths=$(echo ${findIgnorePaths} | cut -c 1-)

printf "\e[0m\n"

echo #Move to new line
printf "$seperator"
echo #Move to new line

echo "Apply 555 permissions to the below directories & all sub directories? "
printf "$seperator"
printf "\e[0;49;96m"

echo
echo "$findIgnorePaths"
echo
find ./ -maxdepth 1 -type d -not -path ./\.git\* -not -path ./administrator/cache\* -not -path ./images\* -not -path ./logs\* -not -path ./cache\* -not -path ./media\* -not -path ./plugins\* -not -path ./tmp\*
echo
find ./ -maxdepth 1 -type d ${findIgnorePaths}
echo



printf "\e[0m\n"
printf "$seperator"

read -r -p "Y/n " response
echo #Move to new line
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]
then
    find ./ -type d $findIgnorePaths -exec chmod 555 {} +
    printf "\e[92mChanged directory permissions to 555\e[0m\n\n"
else
    printf "\e[31mSkipping this step. No directory permissions were set.\e[0m\n\n"
fi

read -r -p "Apply 444 permissions to all files in; ${PWD##*/}? Y/n " response
echo #Move to new line
if [[ $response =~ ^([yY][eE][sS]|[yY])$ ]]
then
    find ./ -type f $findIgnorePaths -exec chmod 444 {} +
    printf "\e[92mChanged file permissions to 444\e[0m\n\n"
else
    printf "\e[31mSkipping this step. No file permissions were set.\e[0m\n\n"
fi

printf "\n\e[92mFinished!\e[0m\n\n"
1个回答

2
这是Bash FAQ 50,它建议您使用数组变量将参数传递给程序:
findIgnorePaths=(-not -path './.git*' -not -path './administrator/cache*' -not -path './images*' -not -path './logs*' -not -path './cache*' -not -path './media*' -not -path './plugins*' -not -path './tmp*')
find ./ -type d "${findIgnorePaths[@]}"

注意,目录通配符应该用单引号括起来,这样在创建变量时就不会被 shell 解释。您的反斜杠转义也是同样的道理;哪种方法更容易阅读取决于个人喜好。
通过 shellcheck.net 运行脚本始终是一个好主意,以查找可能潜藏的任何问题。
另外,/bin/sh 不是 /bin/bash,所以请修复您的 shebang!

啊,谢谢!非常详细和有帮助的回答,这帮助我解决了我的问题。 - Dan J

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接