繁体   English   中英

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

[英]Bash script to run diff command on files in two directories and provide custom side by side output?

编辑 - 可重现代码 Output 和更新的问题

#!/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.

更新的问题- 如何定义、转换或正确比较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/dir1diff命令的 output 行中提取的相同路径字符串或变量相匹配。 我使用awk-F[:]作为分隔符,但可能有其他方法可以做到这一点。 我试图在上方和下方嵌入一些可重现的代码,并带有可重现代码的描述。 更新的问题应该基于上面的编辑,长帖子是为了保留新的上下文和原始帖子。

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

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

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

编辑 - 所需的 Output 格式(脚本名称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

编辑 - 带空格的目录结构(没有:)测试脚本

/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

编辑 - Output 来自运行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

编辑 - 脚本片段 dirt00 在$diffout中存储diff Output

  #!/bin/bash
  if [[ -z "$1" || -z "$2" ]]; then
    printf "\n  Type $ dirt00 Dir1 Dir2\n"
  else
    input1="$1"
    input2="$2"
    diffout=$(diff -qs "$1" "$2")
    # Printf '%s\n' "$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 '%s\n' "$diffout")
  fi

编辑 - Output 来自运行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

编辑 - 可重现的代码脚本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 '%s\n' "$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%-40s\n" "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%-40s\n","diff",$NF,$NF}'
    elif [ $finalword == "identical" ]; then
      snip=${line%" are identical"}
      echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40s\n","same",$NF,$NF}'
    elif [ $firstword == "Common" ]; then
      echo "$line" | awk -F[/] '{printf "  %-8s%-40s%-40s\n","comd",$NF,$NF}'
    else
      echo ""
    fi
  done < <(printf '%s\n' "$diffout")

编辑 - Output 来自运行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) 如何在printf命令中使用下面显示为$2$4的相同 awk 变量,然后使用 output filename.ext 从目录中拆分文件名和扩展名?

dirdiff - bash 脚本

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

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

在命令行上运行 dirdiff 给出以下命令行 output

$ 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

所需的命令行 Output 格式(在顶部重复)

$ 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 function 是您要询问的basename function。

祝你好运!

    diff -qs $1 $2 | gawk -v L=$1 -v R=$2 \
      'BEGIN { printf "\n%-8s%-40s%-40s\n", "INFO", L, R } \
         $NF=="differ" { sub( /.*\//,"",$4) ; printf "%-8s%-40s%-40s\n", "diff", $4, $4 } \
         $NF=="identical" { sub( /.*\//,"",$4) ; printf "%-8s%-40s%-40s\n", "same", $4, $4 } \
         $3==L":" { sub( /.*\//,"",$4) ; printf "%-8s%-40s%-40s\n", "only", $4, "" } \
         $3==R":" { sub( /.*\//,"",$4) ; printf "%-8s%-40s%-40s\n", "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%-40s\n" "BOTH" "$input1" "$input2"
# Printf '%s\n' "$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%-40s\n","diff",$NF,$NF}'
    elif [[ "$finalword" == "identical" ]]; then
      snip=${line%" are identical"}
      echo "$snip" | awk -F[/] '{printf "  %-8s%-40s%-40s\n","same",$NF,$NF}'
    elif [[ "$firstword" == "Common" ]]; then
      echo "$line" | awk -F[/] '{printf "  %-8s%-40s%-40s\n","comd",$NF,$NF}'
    elif [[ "$firstword" == "Only" ]]; then
      snip=${line#"Only in "}
      mdir=${snip%:*}
      name=${snip#*:}
      name=${name# *}
      if [[ "$mdir" == "$input1" ]]; then
        printf "  %-8s%-40s\n" "" "$name"
      else
        printf "  %-8s%-40s%-40s\n" "" "" "$name"
      fi
    else
      echo ""
    fi
  done < <(printf '%s\n' "$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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM