从元组中打印丢失的文件

从元组中打印丢失的文件

我有一个很大的文件元组列表,格式如下:

A_1.txt
A_2.txt 
B_1.txt 
B_2.txt 
C_1.txt  <<
D_1.txt
D_2.txt
E_1.txt
E_2.txt

在一个目录中。正如你所看到的,C_2.txt我的列表中缺少它。我需要找到一种巧妙的方法来查找其中哪些文件缺少其“伙伴”,并使用bash.我想我需要修改这个:

x=$(pwd)
find $x -type f -printf '%f\n' | sort | uniq -c

包含 {0:1},这样它只搜索列表的前 1 个字符,并打印有多少个文件以该第一个字符开头。

预期输出:

2  A
2  B
1  C
2  D
2  E

或(理想)预期输出:

C_1.txt

答案1

循环文件名,提取前缀(第一个之前的字符串_)并检查有多少文件以该前缀开头(我使用过set,但您也可以使用数组并检查其长度)。
如果只有一个,则打印它的名称:

for f in ./*.txt; do
n=${f%%_*}
set -- "${n}"_*
[ $# -eq 1 ] && printf '%s\n' "${f}"
done
set --

答案2

通过管道将您的文件列表传输到

sed -n '$!N;/\(.*\)1.txt\n\12.txt/!{P;D;}'

这总是读取一对行,如果它不是一对,则something1.txt打印something2.txt孤行,因此它给出了“理想的预期输出”。

详细解释:

  • N将下一行追加到模式空间,因此您有两行,包括中间的换行符
  • /\(.*\)1.txt\n\12.txt/是一个“地址”,选择是否执行下一条命令。这可以是行号、范围,或者在本例中是必须与模式空间匹配的正则表达式。.*可以匹配任何字符串,并且通过用 包围它,\(.*\)我们可以稍后将其反向引用为\1。 So\n\12表示换行符,后跟从头开始的字符串,最后是2.因此,我们正在寻找anystring1.txtanystring2.txt
  • 地址后的内容!会反转匹配,因此仅当模式空间与表达式不匹配时才会执行以下操作。如果线路不属于一对,就会出现这种情况。
  • 形成{}命令块,这意味着仅当模式匹配时才会执行其中的所有命令
  • P将模式空间打印到第一个换行符,因此仅打印第一行(因为我们不知道第二行是否属于一对)。
  • 最后D删除第一个换行符之前的模式空间,并从剩余的行开始下一个循环,该行将再次尝试与下一行配对。

我希望这个解释可以帮助您了解一些sed。 *

相关内容