假设我有一个包含这些文件的active/
目录
active/
foo.bar.abc
foo.bar.xyz
foo.bat.abc
archive/
foo.bat.xyz
我想编写一个命令,只输出active/
中的唯一文件名(基于中间项的唯一性)并且与archive/
中已有的任何文件不匹配(同样基于该中期项) )。
示例输出:
foo.bar.abc
说明:输出foo.bar.abc
或foo.bar.xyz
并不重要。自foo.bat.abc
foo.bat.xyz
以来archive/
不是// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
我发现this有助于根据模式识别唯一值,但我无法弄清楚如何将其与我在存档中不匹配的附加条款相结合/
答案 0 :(得分:2)
这里实际上不需要awk,你可以用简单的grep / sed和sort来实现:
(ls ./archive | sed 's/^/1 /'; ls ./active | sed 's/^/2 /') | \
sort --field-separator="." --key="2,2" --uniq --stable | \
grep '^2 ' | sed 's/^2 //'
<强>解释强>
首先列出两个目录并标记哪个行来自哪个目录。然后按照中间部分对两个列表进行排序。选项--field-separator="."
将所有行拆分为dosts上的字段,选项--key="2,2"
告诉按中间字段排序,即按点之间的部分排序。我们使用稳定的排序来确保存档中的行是第一行并告诉排序只打印所有重复行的第一个匹配。
最后,我们只会过滤使用2
标记的行,即来自./active
的行。
示例:强>
active/
foo.aaa.xxx
foo.bar.abc
foo.bar.xyz
foo.bat.abc
zoo.aaa.xxx
zoo.bbb.aaa
archive/
aaa.bbb.zoo
foo.bat.xyz
Result:
foo.aaa.xxx
foo.bar.abc
答案 1 :(得分:1)
使用MainActivity
,GNU grep
和awk
GNU findutils
使用process-substitution <()
运行$ grep -Fxvf <(find active/ -type f -printf '%P\n' | awk -F'.' '!seen[$2]++') <(find archive/ -type f -printf '%P\n' | awk -F'.' '!seen[$2]++')
foo.bar.xyz
/ find
命令并将其传递给awk
以查找差异。
虽然grep
命令列出了指定目录中的文件,每行一个条目,但find
通过保留awk
字未复制的列表来过滤列表。对于2nd
,分隔符为awk
.
仅在以前未见过的情况下,通过在数组中对其进行散列来打印唯一的行。
请记住!seen[$2]++
中的-printf '%P
不 POSIX兼容,并且可以使用find
。建议升级到它以便工作。
其他可能的解决方案,具有类似逻辑,GNU findutils
和comm
,join
的一部分如下: -
GNU coreutils
另一位$ join -v 2 <(find active/ -type f -printf '%P\n' | awk -F'.' '!seen[$2]++') <(find archive/ -type f -printf '%P\n' | awk -F'.' '!seen[$2]++')
foo.bar.xyz
comm