我想find在这篇文章底部的testing案例中改变的文件的文件名。
它输出
before d41d8cd98f00b204e9800998ecf8427e FFF/c.txt d41d8cd98f00b204e9800998ecf8427e FFF/a.txt d41d8cd98f00b204e9800998ecf8427e FFF/b.txt after d41d8cd98f00b204e9800998ecf8427e FFF/c.txt d41d8cd98f00b204e9800998ecf8427e FFF/d.txt d8e8fca2dc0f896fd7cb4cb0031ba249 FFF/b.txt
题
如何获取已更改的文件的文件名?
在这种情况下, a.txt
已经被删除, d.txt
被添加,而b.txt
已经被改变了md5sum。
#!/bin/bash mkdir -p FFF touch FFF/a.txt rm -f FFF/b.txt touch FFF/b.txt touch FFF/c.txt rm -f FFF/d.txt echo "before" find FFF -name "*.txt" -exec md5sum '{}' \; echo "" # makes some changes that I want to catch rm -f FFF/a.txt echo "test" > FFF/b.txt touch FFF/d.txt echo "after" find FFF -name "*.txt" -exec md5sum '{}' \;
有几个选项可以找到自从给定时间点以来发现的文件。 例如,您可以在脚本的起始处touch
一个临时文件,然后运行find -newer tmpfile
来查找自您touch
该临时文件以来已修改的所有文件。
识别在特定状态之间通过哈希(在目录结构中存在)而改变的文件本质上是版本控制系统git所做的,那么为什么不使用它呢? 以下是您的脚本的一个小的修改,它添加了以下步骤:
git diff
来显示这两个提交之间的变化。 修改后的脚本如下所示:
#!/bin/bash # Initialize the current directory as a git repository: git init mkdir -p FFF touch FFF/a.txt rm -f FFF/b.txt touch FFF/b.txt touch FFF/c.txt rm -f FFF/d.txt echo "before" find FFF -name "*.txt" -exec md5sum '{}' \; echo "" # Record the state of the directory as a new commit: git add -A . git commit -m "Initial state" # makes some changes that I want to catch rm -f FFF/a.txt echo "test" > FFF/b.txt touch FFF/d.txt echo "after" find FFF -name "*.txt" -exec md5sum '{}' \; # Record the modified state of the directory as a second commit: git add -A . git commit -m "New state" # Output the difference between those two commits: git diff --name-only HEAD^ HEAD
该脚本的输出是:
Initialized empty Git repository in /home/mark/tmp/foobar/.git/ before d41d8cd98f00b204e9800998ecf8427e FFF/b.txt d41d8cd98f00b204e9800998ecf8427e FFF/c.txt d41d8cd98f00b204e9800998ecf8427e FFF/a.txt [master (root-commit) 8a6d1d9] Initial state 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 FFF/a.txt create mode 100644 FFF/b.txt create mode 100644 FFF/c.txt after d41d8cd98f00b204e9800998ecf8427e FFF/d.txt d8e8fca2dc0f896fd7cb4cb0031ba249 FFF/b.txt d41d8cd98f00b204e9800998ecf8427e FFF/c.txt [master 810b0f5] New state 2 files changed, 1 insertions(+), 0 deletions(-) rename FFF/{a.txt => d.txt} (100%) FFF/a.txt FFF/b.txt FFF/d.txt
最后3行是git diff
命令的输出。
如果将两个find
命令的输出存储到临时文件中,则可以对它们运行diff
来找出已更改的文件。 示例输出将是:
[me@home]$ diff -u ori.temp new.temp | tail -n+4 | grep "^[-+]" | sort -k2 -d41d8cd98f00b204e9800998ecf8427e FFF/a.txt -d41d8cd98f00b204e9800998ecf8427e FFF/b.txt +d41d8cd98f00b204e9800998ecf8427e FFF/d.txt +d8e8fca2dc0f896fd7cb4cb0031ba249 FFF/b.txt
您应该能够解析该输出以确定更改的文件。 第二列给你的文件名称。 以-
开始的行是删除(除非相应的+
存在,这意味着它是一个编辑),而以+
开头的行是增加。
sort -k2
按第二列对输出进行sort -k2
,以便更容易地找到编辑(文件的重复出现)。
解析diff的输出可以用一些awk
甚至纯粹的bash轻松完成。 不幸的是,我的bash / awk-fu没有达到标准,所以这里是我对你的脚本的看法,它使用了一些Python。
#!/bin/bash # set up initial state mkdir -p FFF && touch FFF/a.txt && rm -f FFF/b.txt touch FFF/b.txt FFF/c.txt && rm -f FFF/d.txt # capture current state TMP_ORI="$RANDOM.ori.tmp" find FFF -name "*.txt" -exec md5sum '{}' \; > $TMP_ORI # makes some changes that I want to catch rm -f FFF/a.txt && echo "test" > FFF/b.txt && touch FFF/d.txt # capture new state TMP_NEW="$RANDOM.new.tmp" find FFF -name "*.txt" -exec md5sum '{}' \; > $TMP_NEW # run diff and parse output diff -u $TMP_ORI $TMP_NEW | tail -n+4 | grep "^[-+]" | python -c ' import fileinput modes = {"+" : "added", "-" : "removed" } visited = {} for line in fileinput.input(): # for each line from stdin checksum, file = line.split() # split the columns if file in visited: visited[file] = "modified" # file appeared before else: visited[file] = modes[checksum[0]] # map "+/-" to "added/removed" for file, mode in visited.iteritems(): # print results print "%s\t%s" % (file, mode) ' rm $TMP_ORI $TMP_NEW # delete temp files
运行这个脚本将会得到如下输出:
[me@home] ./sandras_script.sh FFF/d.txt added FFF/a.txt removed FFF/b.txt modified
好的,你的设置是什么?
diff -R
会告诉你在涉及的目录中添加,删除和修改了什么。 您可能必须在Solaris上使用diffdir
或dirdiff
find $dir -mtime
。 这将显示时间戳比-mtime
更新(或更早)的文件。 例如:
$ find $dir -mtime +3
将会发现三天以前的文件:
$ find $dir -mtime -3
会发现三天以下的文件。 有些系统也有-mmin
检查分钟。
如果你正在寻找一些随机的瞬间变化,那么我建议你看看使用版本控制系统。 一个好的版本控制系统将给你灵活性,而不必重新发明轮子。 一个命令(如svn log -rPREV:HEAD -v
)可以为您提供所需的一切。
两个最流行的版本控制系统是Subversion和Git 。 我发现Subversion更易于使用和设置,但是如果您必须与其他人共享您的代码并且没有中央服务器,那么Git会更好。 Baazar有一个很好的界面,也相当简单。 我刚刚开始玩。
另一种方法是使用文件系统监视器,如inotify , dnotify , fam或gamin 。 例子:
inotifywait -m /home/david dnotify -all -r /home/david
添加选项以执行某些命令或将其输出传送到读取/处理循环。