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>-如何定义,转换,或适当地比较var1
到inpd
,以便在输入有空格时产生匹配?如果有更好的方法来找到匹配而不调用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