Linux Bash - 排除带 find 的目录

Linux Bash - excluding directories with find

我在使用我目前正在编写的 bash 脚本时遇到了一些问题,我已经隔离了有问题的代码。

使用变量参数时的查找命令不排除目录。

现在我需要将“-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"

这是Bash FAQ 50, which advises you to use an array variable向程序传递参数:

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[@]}"

注意目录 glob 是单引号的,因此在创建变量时它们不会被 shell 解释。您的反斜杠转义符在做同样的事情;哪个更容易阅读是个人喜好问题。

运行 脚本到 shellcheck.net 始终是发现任何可能潜伏的问题的好主意。

此外,/bin/sh 不是 /bin/bash,所以修复你的 shebang!