我想在本文的底部找到测试用例中更改的文件的文件名。
输出
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 '{}' \;
答案 0 :(得分:4)
有几个选项可供查找自给定时间点以来已更改的文件。例如,您可以在脚本开头touch
一个临时文件,然后运行find -newer tmpfile
以查找自touch
编辑该临时文件以来已修改的所有文件。
答案 1 :(得分:2)
识别通过哈希值在特定状态之间发生变化的文件(以及目录结构中的存在)本质上是版本控制系统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
命令的输出。
答案 2 :(得分:2)
如果将两个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
对第二列的输出进行排序,以便更容易找到编辑内容(文件的重复外观)。
使用少量awk
或甚至纯粹的bash,可以很容易地解析diff的输出。不幸的是,我的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
答案 3 :(得分:2)
好的,你的设置是什么?
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有一个很好的界面,也很简单。我刚刚开始玩它。
答案 4 :(得分:0)
另一种方法是使用文件系统观察程序,例如 inotify , dnotify , fam 或 gamin 。例子:
inotifywait -m /home/david
dnotify -all -r /home/david
添加选项以执行某些命令或将其输出传递给读取/处理循环。