Linux 列出目录 1 但不在目录 2 中的文件,反之亦然?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5279090/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
List files that are in directory1 but NOT in directory2 and vice versa?
提问by eveo
Hey, I started bash shell scripting and I'm trying to make a script for an assignment that when you enter two directories, it will check if they exist and display according error message and if both directories DO exist, it will list the differences between the current directories.
嘿,我开始编写 bash shell 脚本,我正在尝试为分配创建一个脚本,当您输入两个目录时,它将检查它们是否存在并根据错误消息显示,如果两个目录都存在,它将列出之间的差异当前目录。
$ cd dir-1
$ myshellscript . dir-2 (comparing . aka dir-1 against dir-2)
Output:
输出:
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
What I have so far that does not seem to detect whether a directory exists nor list differences:
到目前为止,我似乎没有检测到目录是否存在,也没有列出差异:
dir-1=
dir-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
List of commands I have to work with, otherwise I would have used comm -32 <(ls -la dir-1)
<(ls -la dir-2)
我必须使用的命令列表,否则我会使用 comm -32 <(ls -la dir-1)
<(ls -la dir-2)
http://dl.dropbox.com/u/20930447/index.html
采纳答案by nhed
a bit crude - but the easiest way I always use is (can play with the diff params, I typically use different grep
有点粗糙 - 但我一直使用的最简单的方法是(可以使用 diff 参数,我通常使用不同的 grep
diff -rcw DIR1 DIR2| grep ^Only
then you can sort and format as you like
然后你可以随意排序和格式化
Revised to format (less efficient as we are running diff twice here ... easily solved)
修改为格式(效率较低,因为我们在这里运行了两次 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})
Expanding on the sed expression above:
s=search and replace
the three '@' are separating the expressions (this is TRADITIONALLY done with '/')
^ matches the beginning of a line (forces the rest not to match elsewhere)
. means any character
* means the previous expression (.==match any char) 0-N times
": " is what I matched on from the diff output "Only in X: "
扩展上面的 sed 表达式:
s=search 并替换
三个 '@' 分隔表达式(这是传统上用 '/' 完成的)
^ 匹配一行的开头(强制其余部分不匹配其他地方)。表示任何字符
* 表示前一个表达式(.==匹配任何字符)0-N次“:”是我从差异输出“仅在X中匹配:”
Look Mommy, no hands - now without 'sed' its beginning to be less and less crude
看妈妈,没有手 - 现在没有 '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})
You will probably want to know about IFS ... it needs some reading in the bash manual, but its basically the field separator characters ... by default they include spaces and I don't want the loop to be fed with fractions of lines, just complete lines - so for the duration of the loop I override the default IFS to just newlines and carriage returns.
您可能想了解 IFS ......它需要阅读 bash 手册,但它基本上是字段分隔符......默认情况下,它们包含空格,我不希望循环使用部分行, 只是完整的行 - 所以在循环期间我将默认 IFS 覆盖为换行符和回车符。
BTW maybe your professor is reading stackoverflow, maybe next you wont be allowed to use semicolons ;-) ... (back to 'man bash' ... BTW if you do 'man bash' do it in emacs, makes much easier to read IMO)
顺便说一句,也许你的教授正在阅读 stackoverflow,也许接下来你将不被允许使用分号 ;-) ...(回到 'man bash' ... 顺便说一句,如果你在 emacs 中使用 'man bash' 来做的话,会更容易阅读海事组织)
回答by mpapis
I like to use diff for comparing:
我喜欢使用 diff 进行比较:
diff <(ls -1 dir1) <(ls -1 dir2) | awk '{if (==">") print "in dir 2: "; if(=="<") print "in dir 1: ";}'
You could also analyze it with read:
你也可以用 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
回答by Ezra
The basic recipe of what you want to do, is already done using the diff
utility available on unix-like systems, or using cygwin or GnuWin on Windows. You should exploit this fact.
您想要做的事情的基本配方已经使用类diff
Unix 系统上可用的实用程序完成,或者在 Windows 上使用 cygwin 或 GnuWin。你应该利用这个事实。
If I have directory a
and b
with the following contents:
如果我有目录a
并b
包含以下内容:
ezra@ubuntu:~$ ls -R
.:
a b
./a:
d e f x y z
./b:
i j k x y z
The x
, y
, and z
are exactly the same in each directory.
的x
,y
和z
正好在每个目录相同。
I can achieve what you want using the diff
command like this:
我可以使用这样的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
If I add a new file to each directory (named new
), which are different, I get the following:
如果我向每个不同的目录(名为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
That is, it'll even tell you how, and where the differences in the files occur. Of course, if you don't want or need this functionality, you're free to not use it.
也就是说,它甚至会告诉您文件中的差异发生的方式和位置。当然,如果您不想要或不需要此功能,您可以不使用它。
You also get the following:
您还将获得以下信息:
ezra@ubuntu:~$ diff a c
diff: c: No such file or directory
With the heavy-lifting of this program done by diff, most of what you write will be parsing the output of this command, and then manipulating or outputting it as you see fit.
随着 diff 完成这个程序的繁重工作,您编写的大部分内容将解析此命令的输出,然后按照您认为合适的方式操作或输出它。
One of awk
or sed
might be of particular interest when you're doing this.
回答by Brian Carlton
This almost works. It mainly fails where there are files that are similar locations alphabetically between the two dirs.
这几乎有效。在两个目录之间按字母顺序排列位置相似的文件的情况下,它主要失败。
sdiff -s <(ls -1 dir1) <(ls -1 dir2)
回答by SiegeX
awk '{a[$ ls -1 dir1
file1.txt
file2.txt
file3.txt
file4.txt
file5.txt
$ ls -1 dir2
file1.txt
file3.txt
file4.txt
$ awk '{a[echo "Files that are in $dir1 but not $dir2"
for i in "$dir1/"*; do
[[ -e "$dir2/$i" ]] || (cd "$dir1"; ls -l "$i")
done
echo
]++}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
]++}END{print "some message"; for(i in a)if(a[i]<2){print i}}' <(ls -1 dir2) <(ls -1 dir1)
Proof of Concept
概念证明
##代码##回答by ephemient
That's one half of it.
这是其中的一半。
Replace [[ ... ]]
by [ ... ]
or test ...
if not using Bash.
替换[[ ... ]]
为[ ... ]
或者test ...
如果不使用 Bash。