Bash脚本在两个目录中的文件上运行diff命令并提供自定义并排输出?



EDIT -可复制代码、输出和更新问题

#!/bin/bash
# Input Directory
inpd="/home/space user/space test/space dir1"
# Line To Parse
line="/home/space user/space test/space dir1: space file 1.txt"
# Split Line awk -F[:]
echo ""
var1=$(echo "$line" | awk -F[:] '{print $1}')
echo "  echo var1"
echo "  $var1"
echo ""
echo "  printf var1"
printf "%-2s%s" "" $var1
# var1 == inpd
echo ""
echo ""
echo "  var1 == inpd"
if [ var1 == inpd ]; then
printf "  Match."
else
printf "  No match."
fi
echo ""

$ scriptname

echo var1
/home/space user/space test/space dir1
printf var1
/home/spaceuser/spacetest/spacedir1
var1 == inpd
No match.
<<p>更新问题/strong>-如何定义,转换,或适当地比较var1inpd,以便在输入有空格时产生匹配?如果有更好的方法来找到匹配而不调用awk,它也将解决我的问题。

我在这里找到了解决问题的线索:

如何在bash中删除字符后的所有文本?

$ script-这给出了一个匹配!

#!/bin/bash
# Input Directory
inpd="/home/space user/space test/space dir1"
# Line To Parse
line="/home/space user/space test/space dir1: space file 1.txt"
# var1 keeps everything in 'line' before :
var1=${line%:*}
echo ""
echo "$line"
echo "$var1"
printf "$var1"
# "$var1" == "$inpd"
echo ""
if [ "$var1" == "$inpd" ]; then
printf "  Match."
else
printf "  No match."
fi
echo ""

编辑-为什么长帖子?

我做了一个很长的帖子来展示我的脚本开发工作,但问题现在减少到一个努力匹配任何/path with/ or without spaces/dir1到相同的路径字符串或变量从diff命令的输出行提取。我使用awk-F[:]作为分隔符,但可能有另一种方法来做到这一点。我试图嵌入一些可重复的代码上面和下面的描述可重复的代码。更新后的问题应以上述编辑为基础,长文则保留新的上下文和原文。

对于我的用例,自定义脚本是非递归的;它将处理路径或文件名中的空格;但到目前为止,它会为任何包含冒号:字符的路径或文件名以及包含斜杠/的文件名生成错误。我不确定其他字符或序列会产生错误,我不需要一个更强大的脚本为我目前的目的。

任何输入路径中的空格必须包含在引号dirt "/path with spaces/dir1"中。

到目前为止,我认为如果子目录只出现在一个目录中,如我的测试目录结构所示,那么在没有文件扩展名的情况下,没有办法确定名称是指文件还是指子目录。我打算使用tree列出带有颜色的目录来显示文件和子目录,并使用新的脚本dirt来比较相同或不同的文件。这可能是最好的目录,只有很少的文件和没有很多子目录,这是我的预期用例。

EDIT -所需输出格式(脚本名称dirt使用下面的测试目录)

$ dirt "/home/joe/test dirdiff/dir1" "/home/joe/test dirdiff/dir2"
BOTH    /home/joe/test dirdiff/dir1               /home/joe/test dirdiff/dir2
diff    diff.txt                                  diff.txt
diffout.txt
only1.txt
only2.txt
same    same space.txt                            same space.txt
same    same.txt                                  same.txt
space 1.txt
space 2.txt
subdir1
subdir2
comd    subdirC                                   subdirC

EDIT - Directory Structure With空格(不带:)To Test Script

/home/joe/test dirdiff
├── dir1
│   ├── diff.txt
│   ├── diffout.txt
│   ├── only1.txt
│   ├── same space.txt
│   ├── same.txt
│   ├── space 1.txt
│   ├── subdir1
│   └── subdirC
└── dir2
├── diff.txt
├── only2.txt
├── same space.txt
├── same.txt
├── space 2.txt
├── subdir2
└── subdirC

EDIT -运行diff的输出

$ diff -qs "/home/joe/test dirdiff/dir1" "/home/joe/test dirdiff/dir2"

Files /home/joe/test dirdiff/dir1/diff.txt and /home/joe/test dirdiff/dir2/diff.txt differ
Only in /home/joe/test dirdiff/dir1: diffout.txt
Only in /home/joe/test dirdiff/dir1: only1.txt
Only in /home/joe/test dirdiff/dir2: only2.txt
Files /home/joe/test dirdiff/dir1/same space.txt and /home/joe/test dirdiff/dir2/same space.txt are identical
Files /home/joe/test dirdiff/dir1/same.txt and /home/joe/test dirdiff/dir2/same.txt are identical
Only in /home/joe/test dirdiff/dir1: space 1.txt
Only in /home/joe/test dirdiff/dir2: space 2.txt
Only in /home/joe/test dirdiff/dir1: subdir1
Only in /home/joe/test dirdiff/dir2: subdir2
Common subdirectories: /home/joe/test dirdiff/dir1/subdirC and /home/joe/test dirdiff/dir2/subdirC

EDIT - Script Fragment dirt00将diff的输出存储在$diffout

#!/bin/bash
if [[ -z "$1" || -z "$2" ]]; then
printf "n  Type $ dirt00 Dir1 Dir2n"
else
input1="$1"
input2="$2"
diffout=$(diff -qs "$1" "$2")
# Printf '%sn' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
while IFS= read -r line
do
echo $line
done < <(printf '%sn' "$diffout")
fi

编辑-运行dirt00的输出

$ dirt00 "/home/joe/test dirdiff/dir1" "/home/joe/test dirdiff/dir2"

Files /home/joe/test dirdiff/dir1/diff.txt and /home/joe/test dirdiff/dir2/diff.txt differ
Only in /home/joe/test dirdiff/dir1: diffout.txt
Only in /home/joe/test dirdiff/dir1: only1.txt
Only in /home/joe/test dirdiff/dir2: only2.txt
Files /home/joe/test dirdiff/dir1/same space.txt and /home/joe/test dirdiff/dir2/same space.txt are identical
Files /home/joe/test dirdiff/dir1/same.txt and /home/joe/test dirdiff/dir2/same.txt are identical
Only in /home/joe/test dirdiff/dir1: space 1.txt
Only in /home/joe/test dirdiff/dir2: space 2.txt
Only in /home/joe/test dirdiff/dir1: subdir1
Only in /home/joe/test dirdiff/dir2: subdir2
Common subdirectories: /home/joe/test dirdiff/dir1/subdirC and /home/joe/test dirdiff/dir2/subdirC

EDIT -可复制代码脚本dirt01

#!/bin/bash
input1="/home/joe/test dirdiff/dir1"
input2="/home/joe/test dirdiff/dir2"
diffout="Files /home/joe/test dirdiff/dir1/diff.txt and /home/joe/test dirdiff/dir2/diff.txt differ
Only in /home/joe/test dirdiff/dir1: diffout.txt
Only in /home/joe/test dirdiff/dir1: only1.txt
Only in /home/joe/test dirdiff/dir2: only2.txt
Files /home/joe/test dirdiff/dir1/same space.txt and /home/joe/test dirdiff/dir2/same space.txt are identical
Files /home/joe/test dirdiff/dir1/same.txt and /home/joe/test dirdiff/dir2/same.txt are identical
Only in /home/joe/test dirdiff/dir1: space 1.txt
Only in /home/joe/test dirdiff/dir2: space 2.txt
Only in /home/joe/test dirdiff/dir1: subdir1
Only in /home/joe/test dirdiff/dir2: subdir2
Common subdirectories: /home/joe/test dirdiff/dir1/subdirC and /home/joe/test dirdiff/dir2/subdirC"
# Printf '%sn' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
printf "n  %-8s%-40s%-40sn" "BOTH" "$input1" "$input2"
while IFS= read -r line
do
#echo $line
firstword=$(echo "$line" | awk '{print $1}')
finalword=$(echo "$line" | awk '{print $NF}')
if   [ $finalword == "differ" ]; then
snip=${line%" differ"}
echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40sn","diff",$NF,$NF}'
elif [ $finalword == "identical" ]; then
snip=${line%" are identical"}
echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40sn","same",$NF,$NF}'
elif [ $firstword == "Common" ]; then
echo "$line" | awk -F[/] '{printf "  %-8s%-40s%-40sn","comd",$NF,$NF}'
else
echo ""
fi
done < <(printf '%sn' "$diffout")

EDIT -运行dirt01的输出

$ dirt01

BOTH    /home/joe/test dirdiff/dir1             /home/joe/test dirdiff/dir2
diff    diff.txt                                diff.txt

same    same space.txt                          same space.txt
same    same.txt                                same.txt


comd    subdirC                                 subdirC

我不能写dirt02,完成脚本,没有一个答案更新的问题在这篇文章的顶部。

我留下了原来的问题,并在下面发布,以保留现有答案和评论的背景,非常感谢!

注释-原始问题和下面的帖子

$NF=="differ"$NF=="identicial"开头的两行中:

(1)我如何使用下面所示的相同的awk变量$2$4从目录中分离文件名和扩展名,然后输出文件名。printf命令中的ext ?

dirdiff - bash script

#!/bin/bash
if [[ -z $1 || -z $2 ]]; then
printf "n  Type $ dirdiff Dir1 Dir2n"
else
LEFT=$1
LEFT+=:
RGHT=$2
RGHT+=:
printf "n  %-8s%-40s%-40sn" "" "$1" "$2"
printf "  %-8s%-40s%-40snn" "" "$LEFT" "$RGHT"
diff -qs $1 $2
echo ""
printf "n%-8s%-40s%-40sn" "INFO" "$1" "$2"
diff -qs $1 $2 | awk -v L=$LEFT -v R=$RGHT 
'$NF=="differ" {printf "%-8s%-40s%-40sn","diff", $2, $4} 
$NF=="identical" {printf "%-8s%-40s%-40sn","same", $2, $4} 
$3==L {printf "%-8s%-40sn","", $4} 
$3==R {printf "%-8s%-40s%-40sn","", "", $4}'
fi

这是调试和开发脚本,运行两次命令$ diff -qs $1 $2。第一次显示原始输出。第二次将输出管道输出到awk,我试图在命令行上解析行并格式化输出。我的问题与剧本的最后五行有关。编辑:我在awk中解决了printf语法问题,如代码所示。

在命令行上运行dirdiff会得到以下命令行输出

$ dirdiff /usr/local/adm/sys /mnt/ssdroot/home/joe/admin/sys
/usr/local/adm/sys                      /mnt/ssdroot/home/joe/admin/sys
/usr/local/adm/sys:                     /mnt/ssdroot/home/joe/admin/sys:
Only in /mnt/ssdroot/home/joe/admin/sys: bashrc.txt
Only in /usr/local/adm/sys: debpkgs.txt
Files /usr/local/adm/sys/direnv.txt and /mnt/ssdroot/home/joe/admin/sys/direnv.txt differ
Only in /usr/local/adm/sys: dpiDec2022.txt
Only in /mnt/ssdroot/home/joe/admin/sys: mypkgs.txt
Only in /mnt/ssdroot/home/joe/admin/sys: pyenv.txt
Files /usr/local/adm/sys/ssh.txt and /mnt/ssdroot/home/joe/admin/sys/ssh.txt are identical
Files /usr/local/adm/sys/usbquirks.txt and /mnt/ssdroot/home/joe/admin/sys/usbquirks.txt differ

INFO    /usr/local/adm/sys                      /mnt/ssdroot/home/joe/admin/sys
bashrc.txt
debpkgs.txt
diff    /usr/local/adm/sys/direnv.txt           /mnt/ssdroot/home/joe/admin/sys/direnv.txt
dpiDec2022.txt
mypkgs.txt
pyenv.txt
same    /usr/local/adm/sys/ssh.txt              /mnt/ssdroot/home/joe/admin/sys/ssh.txt
diff    /usr/local/adm/sys/usbquirks.txt        /mnt/ssdroot/home/joe/admin/sys/usbquirks.txt

期望的命令行输出格式(顶部重复)

$ dirdiff /usr/local/adm/sys /mnt/ssdroot/home/joe/admin/sys
INFO    /usr/local/adm/sys                        /mnt/ssdroot/home/joe/admin/sys
bashrc.txt
debpkgs.txt
diff    direnv.txt                                direnv.txt
dpiDec2022.txt
mypkgs.txt
pyenv.txt
same    ssh.txt                                   ssh.txt
diff    usbquirks.txt                             usbquirks.txt

希望这对你有帮助。我认为sub函数是你所要求的basename函数。

祝你好运!

diff -qs $1 $2 | gawk -v L=$1 -v R=$2 
'BEGIN { printf "n%-8s%-40s%-40sn", "INFO", L, R } 
$NF=="differ" { sub( /.*//,"",$4) ; printf "%-8s%-40s%-40sn", "diff", $4, $4 } 
$NF=="identical" { sub( /.*//,"",$4) ; printf "%-8s%-40s%-40sn", "same", $4, $4 } 
$3==L":" { sub( /.*//,"",$4) ; printf "%-8s%-40s%-40sn", "only", $4, "" } 
$3==R":" { sub( /.*//,"",$4) ; printf "%-8s%-40s%-40sn", "only", "", $4 } '
INFO    dir1                                    dir2                                    
only                                            bashrc.txt                              
only    debpkgs.txt                                                                     
diff    direnv.txt                              direnv.txt                              
only    dpiDec2022.txt                                                                  
only                                            mypkgs.txt                              
only                                            pyenv.txt                               
same    ssh.txt                                 ssh.txt                                 
diff    usbquirks.txt                           usbquirks.txt 

带有空格(不带:)的目录结构

/home/joe/test dirdiff
├── dir1
│   ├── diff.txt
│   ├── diffout.txt
│   ├── only1.txt
│   ├── same space.txt
│   ├── same.txt
│   ├── space 1.txt
│   ├── subdir1
│   └── subdirC
└── dir2
├── diff.txt
├── only2.txt
├── same space.txt
├── same.txt
├── space 2.txt
├── subdir2
└── subdirC

可复制的脚本作品路径&包含空格但不包含冒号的名称

#!/bin/bash
input1="/home/joe/test dirdiff/dir1"
input2="/home/joe/test dirdiff/dir2"
diffout="Files /home/joe/test dirdiff/dir1/diff.txt and /home/joe/test dirdiff/dir2/diff.txt differ
Only in /home/joe/test dirdiff/dir1: diffout.txt
Only in /home/joe/test dirdiff/dir1: only1.txt
Only in /home/joe/test dirdiff/dir2: only2.txt
Files /home/joe/test dirdiff/dir1/same space.txt and /home/joe/test dirdiff/dir2/same space.txt are identical
Files /home/joe/test dirdiff/dir1/same.txt and /home/joe/test dirdiff/dir2/same.txt are identical
Only in /home/joe/test dirdiff/dir1: space 1.txt
Only in /home/joe/test dirdiff/dir2: space 2.txt
Only in /home/joe/test dirdiff/dir1: subdir1
Only in /home/joe/test dirdiff/dir2: subdir2
Common subdirectories: /home/joe/test dirdiff/dir1/subdirC and /home/joe/test dirdiff/dir2/subdirC"
printf "n  %-8s%-40s%-40sn" "BOTH" "$input1" "$input2"
# Printf '%sn' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
while IFS= read -r line
do
#echo $line
firstword=$(echo "$line" | awk '{print $1}')
finalword=$(echo "$line" | awk '{print $NF}')
if   [[ "$finalword" == "differ" ]]; then
snip=${line%" differ"}
echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40sn","diff",$NF,$NF}'
elif [[ "$finalword" == "identical" ]]; then
snip=${line%" are identical"}
echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40sn","same",$NF,$NF}'
elif [[ "$firstword" == "Common" ]]; then
echo "$line" | awk -F[/] '{printf "  %-8s%-40s%-40sn","comd",$NF,$NF}'
elif [[ "$firstword" == "Only" ]]; then
snip=${line#"Only in "}
mdir=${snip%:*}
name=${snip#*:}
name=${name# *}
if [[ "$mdir" == "$input1" ]]; then
printf "  %-8s%-40sn" "" "$name"
else
printf "  %-8s%-40s%-40sn" "" "" "$name"
fi
else
echo ""
fi
done < <(printf '%sn' "$diffout")

$ scriptname

BOTH    /home/joe/test dirdiff/dir1             /home/joe/test dirdiff/dir2
diff    diff.txt                                diff.txt
diffout.txt
only1.txt
only2.txt
same    same space.txt                          same space.txt
same    same.txt                                same.txt
space 1.txt
space 2.txt
subdir1
subdir2
comd    subdirC                                 subdirC

最新更新