我创建了两个 .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)
.