根据两个文本文件的差异删除文件

根据两个文本文件的差异删除文件

我创建了两个 .txt 文件,如下所示:

5fba026dcf271c6fa174b9fc2fc1fefadf1370f9 ./.changeFiles/change/addImage1.change  
bb352fba5807f4d03ea11abb00e411b00ce38673  ./.changeFiles/change/addImage2.change  
999eea42e4e72431695815456a3ac16796df5eed  ./.changeFiles/change/addSurface1.change

一个是给定目录中以 .change 或 .tstwf 结尾的所有文件的列表,另一个是该列表的排序版本,其中删除了重复条目(基于 shasum)。

当我对两个文件使用 colordiff -u 时,所有更改都是我想要删除的文件。有数百个文件需要删除,我不想手动执行此操作...

所以我的问题是:如何从目录中删除未包含在sorted.txt 中并显示在diff 中的文件?

编辑1:

workflows.txt(原始文件):

23ded53098d5d233c0a54af482542ba7a42860d3  ./encryption/AFPtoPDFwEncryption.tstwf
24a37e00de73a58736be1aee56d4b073e75a994f  ./workflows-from-will/workflow/AFPtoPDF.tstwf
2532934d268bb6eddc6a018e3469b0a53a794e10  ./workflows-from-will/workflow/change/table.without.emptycells.rotation.270.mark-content.change
264a08fef59d9b9c18a857e2532f0b7b5a92c60b  ./pageModification/AFPtoPDFwFillRectMod1.tstwf
2680a37bb22512bf3119e3991bb2c814cb23fb77  ./workflows-from-will/workflow/AFPtoPDFwHyperlinks.tstwf
268635261e91a4caf1a09979ffdb8163d4d22c8a  ./AFPmicr.tstwf
268635261e91a4caf1a09979ffdb8163d4d22c8a  ./workflows-from-will/eds-0923/AFPmicr.tstwf

workflows-sorted.txt(要保留的所有此类文件的列表):

0bdbcbed279e2df9149de319253609f11b19d689  ./textModification/AFPtoPDFwReplaceTextMod2.tstwf
0d0ebfb8d519ff84e3dd86771d067bdeea835df6  ./pageModification/AFPtoPDFwSoftClipMod1.tstwf
0dcafe876ea8574619664920ec5b1fdbff3ca218  ./workflows-from-will/AFPtoPDF_CE003A01.tstwf
0e55506bf5d7694d8cda9467a5809ea75c486fb1  ./workflows-from-will/workflow/change/pdf.change
0ec03992e19a12520f131f89cd9060c2e4ba2be2  ./workflows-from-will/AFPNOPIndexCallback.tstwf
0f1dca3e5d9b17f11c194b250096fc15891b9998  ./stapling/AFPtoPDFwStapling1.tstwf

另外,在我的进一步研究中,我遇到了命令“comm”,它似乎可以用来隔离我想要删除的文件。

答案1

因此,您想要删除 中列出的文件workflows.txt,但 中列出的文件除外workflows-sorted.txt。您可以通过去掉校验和、对名称进行排序并运行来获取文件列表comm提取仅存在于 中的行workflows.txt。在支持进程替换的 shell 中(ksh93、bash、zsh):

comm -23 <(<workflows.txt sed 's/^[^ ]*[ ][ ]*//' | sort) \
         <(workflows-sorted.txt sed 's/^[^ ]*[ ][ ]*//' | sort)

comm -23删除仅第二个参数 ( ) 中存在的行-2以及两个文件 ( ) 中存在的行-3,从而仅保留第一个参数中存在的行,而不保留第二个参数中存在的行。请记住,这comm需要对输入文件进行排序。

要删除它们:

comm -23 <(<workflows.txt sed 's/^[^ ]*[ ][ ]*//' | sort) \
         <(workflows-sorted.txt sed 's/^[^ ]*[ ][ ]*//' | sort) |
xargs -I rm -- {}

如果文件名不包含任何空格xargs rm或.或者,如果您支持这些选项,您也可以在最后一行添加。如果所有文件名都以或开头(或保证不以 开头的任何内容),则不需要。rm\'"tr '\n' '\0' | xargs -0 rm --xargs -d '\n' rm --xargs--/./-

答案2

如果您的文件名没有空格,这应该会为您提供要删除的重复文件的列表:

awk 'c[$1]++' workflows.txt > erasefiles.txt

然后,只需删除所有它们(首先使用 echo 直到您确定这完全符合您的需要)(在 bash 中):

rm $(awk '{print $2}' erasefiles.txt)

如果您的文件可能有空格(或其他奇怪的字符,除了换行 -\n和零\0):

awk '{$1=""; print}' erasefiles.txt | tr '\n' '\0' | xargs -0 -r rm --

答案3

为一个一次性工作中,我将从diff输出开始,并将其编辑到要删除的文件列表中(如果无聊,将该任务留给sed(1)Perl 脚本或类似的东西)。仔细检查列表后,通过例如(bash(1)!)运行它:

rm $(< list-of-files-to-axe)

可以用-f-i标记来调味。

自动化这将需要更多的工作(并引入太多的陷阱),对于偶尔使用来说是值得的。对于重复使用,请使用 Perl 或 Python 等功能强大的脚本语言编写。远离特殊用途语言,例如awk(1).

相关内容