列出目录1中但不在目录2中的文件,反之亦然?

时间:2011-03-11 22:34:46

标签: linux bash shell

嘿,我启动了bash shell脚本,我正在尝试创建一个分配脚本,当你输入两个目录时,它将检查它们是否存在并根据错误消息显示,如果两个目录都存在,它将列出当前目录之间的差异。

$ cd dir-1
$ myshellscript . dir-2 (comparing . aka dir-1 against dir-2) 

输出:

Files that are in . but not in dir-2
-rw------- 1 ddddd users   1 2011-03-1 01:26 123123123

Files that are in dir-2 but not in .
-rw------- 1 ddddd users   1 2011-03-1 01:26 zzzzzzzzzzzz

到目前为止,我似乎没有检测目录是否存在,也没有列出差异:

dir-1=$1
dir-2=$2

if [ $# > 2  ]
   then
      echo "Usage: compdir dir-name1 dir-name 2"
      exit 1
   elif [ $# < 2 ]
      then
         echo "Usage: comdir dir-name1 dir-name 2"
   elif [ ! -d "$@" ]
      then
         echo "/$@ is not a valid existing directory"
   else
      exit 0
fi

echo $dir-1
echo $dir-2

我必须使用的命令列表,否则我会使用comm -32 <(ls -la dir-1) <(ls -la dir-2)

http://dl.dropbox.com/u/20930447/index.html

6 个答案:

答案 0 :(得分:34)

有点粗糙 - 但我总是使用最简单的方法是(可以使用diff params,我通常使用不同的grep

diff -rcw DIR1 DIR2| grep ^Only

然后您可以根据需要进行排序和格式化

修改格式化(因为我们在这里运行diff两次效率较低......很容易解决)

echo files only in $dir1
LST=$(diff ${dir1} ${dir2}| grep "^Only in ${dir1}"| sed 's@^.*: @@')
(cd ${dir1}; ls -l ${LST})

echo files only in $dir2
LST=$(diff ${dir1} ${dir2}| grep "^Only in ${dir2}"| sed 's@^.*: @@')
(cd ${dir2}; ls -l ${LST})

扩展上面的sed表达式:
  s =搜索并替换
  三个'@'分隔表达式(这是传统的'/')   ^匹配一行的开头(强制其余部分不与其他地方匹配)   。是指任何人物   *表示前一个表达式(。==匹配任何字符)0-N次   “:”是我从diff输出“仅在X:”

中匹配的

看看妈妈,没有手 - 现在没有'sed'开始变得越来越少了原油

XIFS="${IFS}"
IFS=$'\n\r'
for DIFFLINE in $(diff ${dir1} ${dir2}|grep ^Only); do
  case "${DIFFLINE}" in
   "Only in ${dir1}"*)  
    LST1="${LST1} ${DIFFLINE#*:}"
    ;;
   "Only in ${dir2}"*)  
    LST2+="${DIFFLINE#*:}"
    ;;
  esac
done
IFS="${XIFS}"

echo files only in $dir1
(cd ${dir1}; ls -l ${LST1})

echo files only in $dir2
(cd ${dir2}; ls -l ${LST2})

您可能想了解IFS ...它需要在bash手册中阅读一些内容,但它基本上是字段分隔符...默认情况下它们包含空格,我不希望循环被输入行的分数,只是完整的行 - 因此在循环的持续时间内,我将默认的IFS覆盖为换行符和回车符。

BTW也许你的教授正在阅读stackoverflow,也许接下来你不会被允许使用分号;-) ...(回到'man bash'... BTW,如果你做'男人bash'在emacs做,做更容易阅读IMO)

答案 1 :(得分:2)

这几乎可行。它主要在两个目录之间按字母顺序存在类似位置的文件时失败。

sdiff -s <(ls -1 dir1) <(ls -1 dir2)

答案 2 :(得分:1)

我喜欢使用diff进行比较:

diff <(ls -1 dir1) <(ls -1 dir2) | awk '{if ($1==">") print "in dir 2: "$2; if($1=="<") print "in dir 1: "$2;}'

你也可以用read来分析它:

diff <(ls -1 $dir1) <(ls -1 $dir2) | while read status filename
do
  [ "$status" == "<" ] && echo "in dir 1: $(ls -l $dir1/$filename)"
  [ "$status" == ">" ] && echo "in dir 2: $(ls -l $dir2/$filename)"
done

答案 3 :(得分:1)

您想要做的基本配方已经使用类似unix的系统上的diff实用程序,或者在Windows上使用cygwin或GnuWin完成。你应该利用这个事实。

如果我的目录ab包含以下内容:

ezra@ubuntu:~$ ls -R
.:
a  b

./a:
d  e  f  x  y  z

./b:
i  j  k  x  y  z

xyz在每个目录中完全相同。

我可以使用diff命令实现您想要的效果:

ezra@ubuntu:~$ diff a b
Only in a: d
Only in a: e
Only in a: f
Only in b: i
Only in b: j
Only in b: k

如果我将新文件添加到每个目录(名为new),这些目录不同,我会得到以下内容:

ezra@ubuntu:~$ diff a b
Only in a: d
Only in a: e
Only in a: f
Only in b: i
Only in b: j
Only in b: k
diff a/new b/new
1c1
< ezraa
---
> ezra

也就是说,它甚至可以告诉你文件中的差异是如何发生的。当然,如果您不想要或不需要此功能,您可以不使用它。

您还可以获得以下内容:

ezra@ubuntu:~$ diff a c
diff: c: No such file or directory

由于diff完成了这个程序的繁重工作,你编写的大部分内容都将解析这个命令的输出,然后根据你的需要操作或输出它。

当您这样做时,awksed中的一个可能会特别感兴趣。

答案 4 :(得分:1)

awk '{a[$0]++}END{print "some message"; for(i in a)if(a[i]<2){print i}}' <(ls -1 dir2) <(ls -1 dir1)

概念证明

$ ls -1 dir1
file1.txt
file2.txt
file3.txt
file4.txt
file5.txt

$ ls -1 dir2
file1.txt
file3.txt
file4.txt

$ awk '{a[$0]++}END{print "Files in dir1 but NOT in dir2"; for(i in a)if(a[i]<2){print i}}' <(ls -1 dir2) <(ls -1 dir1)
Files in dir1 but NOT in dir2
file5.txt
file2.txt

答案 5 :(得分:1)

echo "Files that are in $dir1 but not $dir2"
for i in "$dir1/"*; do
    [[ -e "$dir2/$i" ]] || (cd "$dir1"; ls -l "$i")
done
echo

这是它的一半。

如果不使用Bash,请将[[ ... ]]替换为[ ... ]test ...