我创建了一个脚本,以递归方式查找文件夹的内容,排除某些路径,然后要求对结果的每一行采取操作。
find命令本身工作正常,并按预期排除路径。看起来像这样:
$SOURCE="FOLDER/"
$EXCLUDESTRING="! -path \"FOLDER/*/.svn/*\" ! -path \"FOLDER/uploads/*\" ! -path \"FOLDER/ai-cache/*\""
find "$SOURCE"* $EXCLUDESTRING # uploads and ai-cache folders are not included in the results
但是当我将结果传递给While循环时,它不会考虑排除。
find "$SOURCE"* $EXCLUDESTRING -print0 | while read -d $'\0' file_1
do
echo $file_1 # uploads and ai-cache folders are included in the results
if statement ...
more commands ...
done
我想提一下,目标是找到所需的文件和文件夹,并在不使用数组的情况下即时处理它们。
更新
对于那些对我的脚本感兴趣的人(逐步单向同步)或者可以测试(非常感谢)这是一个更详细的副本:
#!/bin/bash
excludepath=( "*/.svn/*" "uploads/*" "design/*" "ai-cache/*" )
bold=`tput bold`
normal=`tput sgr0`
validsource="false"
while [ "$validsource" == "false" ]
do
echo ""
echo "Specify project to compare :"
echo -n "/home/myaccount/public_html/projects/"
read -e project
project=`echo "$project" | sed -e "s/\/*$//" `
projectpath="/home/myaccount/public_html/projects/$project"
source="$(readlink -f $projectpath)/"
if [ -d "$source" ];then
validsource="true"
else
echo "The working copy cannot be found ($projectpath)."
fi
done
echo "Compare project with folder :"
read -e target
excludestring=""
for i in "${excludepath[@]}"
do
excludestring="$excludestring ! -path \"$source$i\""
done
echo ""
echo "______________________________________________"
echo ""
echo "COMPARISON IN PROGRESS ..."
echo "______________________________________________"
echo ""
echo "List of paths excluded from the comparison: ${excludepath[@]}"
echo "Executed command : find \"$source\"* $excludestring"
echo ""
liveexclude=()
find "$source"* $excludestring -print0 | while read -d $'\0' file_1
do
file=$( echo "$file_1" | sed "s,$source,,g" ) # Strip base path
file_2=$( echo "$file_1" | sed "s,$source,$target,g" ) # Getting file path in $target
dir=$( dirname "$file_2" | sed "s,$target,,g" )
dir_1=$( dirname "$file_1" )
dir_2=$( dirname "$file_2" )
#Check for live excluded folders
process="true"
for i in "${liveexclude[@]}"
do
if [[ $file_1 == "$i"* ]]
then
process="false"
break
fi
done
if [ "$process" == "true" ];then
if [ -d "$file_1" ];then
if [ ! -d "$file_2" ] # Checking if sub-dir exists in $target
then
while [ "$confirm" != "y" ] && [ "$confirm" != "n" ]
do
echo ""
echo "${bold}Folder${normal} \"$file\" doesn't exist."
echo -n "Would you like to ${bold}create it and its entire contents${normal} ? (y/n) "
read -e confirm </dev/tty
done
if [ "$confirm" == "y" ];then
mkdir -p $file_2 # Creating if sub-dir missing
cp -r "$file_1/"* "$file_2"
fi
confirm=""
liveexclude+=("$file_2")
fi
else
if [ -f "$file_1" ];then
if [ -f "$file_2" ] # Checking if file exists in $target
then
cksum_file_1=$( cksum "$file_1" | cut -f 1 -d " " ) # Get cksum of file in $source
cksum_file_2=$( cksum "$file_2" | cut -f 1 -d " " ) # Get cksum of file in $target
if [ $cksum_file_1 -ne $cksum_file_2 ] # Check if cksum matches
then
while [ "$confirm" != "y" ] && [ "$confirm" != "n" ]
do
if [ "$file_1" -nt "$file_2" ]
then
echo ""
echo "${bold}File${normal} \"$file\" is not updated."
echo -n "Would you like to ${bold}replace${normal} it ? (y/n) "
else
echo ""
echo "${bold}File${normal} \"$file\" was modified."
echo "${bold}CAUTION${normal}: The file \"$file_2\" is newer than the file \"$file_1\""
echo -n "Would you still ${bold}overwrite${normal} it ? (y/n) "
fi
read -e confirm </dev/tty
done
if [ "$confirm" == "y" ];then
cp "$file_1" "$file_2" # Copy if cksum mismatch
fi
confirm=""
fi
else
while [ "$confirm" != "y" ] && [ "$confirm" != "n" ]
do
echo ""
echo "${bold}File${normal} \"$file\" doesn't exist."
echo -n "Would you like to ${bold}copy${normal} it ? (y/n) "
read -e confirm </dev/tty
done
if [ "$confirm" == "y" ];then
cp "$file_1" "$file_2" # Copy if file does not exist.
fi
confirm=""
fi
fi
fi
fi
done
PS。如果需要进行详细检查,我们使用此脚本在现有项目上应用新更改。
答案 0 :(得分:2)
不要将命令放在字符串中,而是放在数组中。并且不要在作业的左侧使用一美元(我们不在Perl / PHP中)。哦,避免使用大写变量名。它看起来很难看;你好像在喊这个变量的名字;但更严重的是,它可能会与保留名称冲突(例如PATH
,LINES
,GROUPS
,USERS
等等;如果您坚持使用小写变量名称,那么您就安全了(而且它更漂亮!)。
source=FOLDER/
excludeary=( \! -path "FOLDER/*/.svn/*" \! -path "FOLDER/uploads/*" \! -path "FOLDER/ai-cache/*" )
find "$source" "${excludeary[@]}" -print0 | while IFS= read -r -d '' file_1
do
echo "$file_1" # uploads and ai-cache folders are included in the results
if statement ...
more commands ...
done
编辑。以下是一个小例子:
$ mkdir Test
$ cd Test
$ mkdir -p {excl,incl}/{1,2}
$ touch {excl,incl}/{1,2}/{a,b}
$ tree
.
|-- excl
| |-- 1
| | |-- a
| | `-- b
| `-- 2
| |-- a
| `-- b
`-- incl
|-- 1
| |-- a
| `-- b
`-- 2
|-- a
`-- b
6 directories, 8 files
$ source=~/Test
$ excludeary=( \! -path "$source/excl/*" )
$ find "$source" "${excludeary[@]}"
/home/gniourf/Test
/home/gniourf/Test/excl
/home/gniourf/Test/incl
/home/gniourf/Test/incl/1
/home/gniourf/Test/incl/1/a
/home/gniourf/Test/incl/1/b
/home/gniourf/Test/incl/2
/home/gniourf/Test/incl/2/a
/home/gniourf/Test/incl/2/b
! -path
的工作原理。请注意,您仍然拥有/home/gniourf/Test/excl
文件夹(但不包含其子文件夹)。也许你想要-prune
代替:
$ pruneary=( \! \( -type d -name excl -prune \) )
$ find "$source" "${pruneary[@]}"
/home/gniourf/Test
/home/gniourf/Test/incl
/home/gniourf/Test/incl/1
/home/gniourf/Test/incl/1/a
/home/gniourf/Test/incl/1/b
/home/gniourf/Test/incl/2
/home/gniourf/Test/incl/2/a
/home/gniourf/Test/incl/2/b
或者将所有1
目录与excl
目录一起排除:
$ excludeary=( \! \( -type d \( -name excl -o -path '*/1' \) -prune \) )
$ find "$source" "${excludeary[@]}"
/home/gniourf/Test
/home/gniourf/Test/incl
/home/gniourf/Test/incl/2
/home/gniourf/Test/incl/2/a
/home/gniourf/Test/incl/2/b
答案 1 :(得分:0)
当我删除所有双引号并将所有内容放在单引号中时,所有必要的排除对我都有用:
EXCLUDESTRING='! -path FOLDER/*/.svn/* ! -path \"FOLDER/uploads/* ! -path FOLDER/ai-cache/*'