提问人:Marc-Antoine Xavier 提问时间:12/7/2022 最后编辑:Marc-Antoine Xavier 更新时间:12/8/2022 访问量:39
使用带有数组和值的 diff 时出现问题 SHELL [duplicate]
Issue using diff with array and value quoted SHELL [duplicate]
问:
嗨,大家好,我在使用 diff 时遇到了问题。
在我的脚本中,我试图将 1 个目录中的所有文件与其他 2 个目录中的所有文件进行比较 使用 diff 进行比较是文件是相同的。
这是我的剧本: `
#!/bin/bash
files1=()
files2=()
# Directories to compare. Adding quotes at the begining and at the end of each files found in content1 & content3
content2=$(find /data/logs -name "*.log" -type f)
content1=$(find /data/other/logs1 -type f | sed 's/^/"/g' | sed 's/$/"/g')
content3=$(find /data/other/logs2 -type f | sed 's/^/"/g' | sed 's/$/"/g')
# ADDING CONTENT INTO FILES1 & FILES2 ARRAY
while read -r line; do
files1+=("$line")
done <<< "$content1"
# content1 and content3 goes into the same array
while read -r line3;do
files1+=("$line3")
done <<< "$content3"
while read -r line2; do
files2+=("$line2")
done <<< "$content2"
# Here i'm trying to compare 1 by 1 the files in files2 to all files1
for ((i=0; i<${#files2[@]}; i++))
do
for ((j=0; j<${#files1[@]}; j++))
do
if [[ -n ${files2[$i]} ]];then
diff -s "${files2[$i]}" "${files1[$j]}" > /dev/null
if [[ $? == 0 ]]; then
echo ${files1[$j]} "est identique a" ${files2[$i]}
unset 'files2[$i]'
break
fi
fi
done
done
#SHOW THE FILES WHO DIDN'T MATCHED
echo ${files2[@]}
`
当我尝试差异时,我遇到了以下问题: diff: “/data/content3/other/log2/perso log/somelog.log”: 没有这样的文件或目录
但是当我在做的时候
ll "/data/content3/other/log2/perso log/somelog.log" -rw-rw-r-- 2 lopom lopom 551M 30 oct. 18:53 '/data/content3/other/logs2/perso log/somelog.log'
所以文件存在。
我需要这些引号,因为有时路径中有空间
some1 知道如何解决这个问题吗?
谢谢。
我已经尝试用单引号更改引号,但它没有修复它
答:
首先,不要这样做——
content2=$(find /data/logs -name "*.log" -type f)
content1=$(find /data/other/logs1 -type f | sed 's/^/"/g' | sed 's/$/"/g')
content3=$(find /data/other/logs2 -type f | sed 's/^/"/g' | sed 's/$/"/g')
不要将所有这些堆叠到单个变量中。这是在问十种晦涩难懂的麻烦。更重要的是,这些调用将引号作为文件名的一部分嵌入到数据中,这可能是导致崩溃的原因,因为名称中没有带有引号的实际文件。sed
diff
另外,如果您要丢弃输出,而只是用于检查文件是否相同,请尝试。它是静默的,而且速度要快得多,因为它在第一个不同的字节处退出,而无需读取两个文件的其余部分并生成报告。如果有很多文件,这将加起来。diff
cmp
-s
如果日志是目录中唯一的东西,并且您不必扫描子目录,并且文件名不能同时出现在 /data/other/logs1 和 /data/other/logs2 中,但您非常确定它至少会出现在其中一个中......然后简化:
for f in /data/logs/*.log # I'll assume these are all files...
do t=/data/other/logs[12]/"${f#/data/logs/}" # always just one?
if cmp -s "$f" "$t" # cmp -s *has* no output
then echo "$t est identique a $f" # files are same
elif [[ -e "$t" ]] # check t exists
then echo "$t diffère de $f" # maybe ls -l "$f" "$t" ?
else echo "$t n'existe pas" # report it does not
fi
done
这不需要数组,没有,没有调用等。find
sed
如果您确实需要读取子目录,请使用 glob 来处理它,这样您就不必担心使用 .(c.f. https://mywiki.wooledge.org/ParsingLs 出于某些原因。shopt
read
shopt -s globstar
for f in /data/logs/**/*.log # globstar makes ** match at arbitrary depth
do for t in /data/other/logs[12]/**/"${f#/data/logs/}" # if >1 possible hit
do if cmp -s "$f" "$t"
then echo "$t est identique a $f"
elif [[ -e "$t" ]]
then echo "$t diffère de $f"
else echo "$t n'existe pas" # $t will be the glob, one iteration
fi
done
done
评论
readarray -d '' files1 < <(find /data/logs -name '*.log' -type f -print0)
-- 首先创建字符串,将文件名混合在一起,在字符串中添加引号,然后尝试将该内容解析为数组,这只是添加了额外的失败模式。/