我的Linux系统中有两个目录,/dir
和/dir2
两个都有超过4000个JSON文件。每个文件的JSON内容就像
{
"someattribute":"someValue",
"url":[
"https://www.someUrl.com/xyz"
],
"someattribute":"someValue"
}
请注意,URL是一个数组,但是它始终包含一个元素(URL)。
URL使文件唯一。如果/dir
和/dir2
中的文件具有相同的url,则该文件是重复的,需要将其删除。
我想最好使用shell命令来自动执行此操作。有意见我应该怎么做吗?
答案 0 :(得分:5)
使用jq获取重复列表:
jq -nr 'foreach inputs.url[0] as $u (
{}; .[$u] += 1; if .[$u] > 1
then input_filename
else empty end
)' dir/*.json dir2/*.json
要删除它们,请将命令输出上方的管道传输到xargs:
xargs -d $'\n' rm --
或者,为了与具有-0
但没有-d
的非GNU xargs兼容:
tr '\n' '\0' | xargs -0 rm --
请注意,文件名不得包含换行符。
答案 1 :(得分:1)
这是一个快速且肮脏的bash脚本,它使用jq从json文件中提取URL,并使用awk来检测和删除重复项:
#!/bin/bash
rm -f urls-dir1.txt urls-dir2.txt
for file in dir1/*.json; do
printf "%s\t%s\n" "$file" $(jq '.url[0]' "$file") >> urls-dir1.txt
done
for file in dir2/*.json; do
printf "%s\t%s\n" "$file" $(jq '.url[0]' "$file") >> urls-dir2.txt
done
awk -F $'\t' 'FNR == NR { urls[$2] = 1; next }
$2 in urls { system("rm -f \"" $1 "\"") }' urls-dir1.txt urls-dir2.txt
rm -f urls-dir1.txt urls-dir2.txt
假定dir2中有要删除的文件作为重复文件,而dir1中的文件应保持不变。
答案 2 :(得分:1)
您可以使用以下Java方法来实现此目的:
Set<String> urls = new HashSet<>();
try (Stream<Path> paths = Files.list(Paths.get("/path/to/your/folder"))) {
paths
.map(path -> new FileInfo(path, extractUrl(path)))
.filter(info -> info.getUrl() != null)
.filter(info -> !urls.add(info.getUrl()))
.forEach(info -> {
try {
Files.delete(info.getPath());
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
e.printStackTrace();
}
这使用以下FileInfo
类:
public class FileInfo {
private Path path;
private String url;
// constructor and getter
}
首先,它读取给定目录中的所有文件并提取URL。它借助HashSet
过滤所有重复项。最后,所有包含重复URL的文件都将被删除。
有多个选项可从每个文件中提取url
:
使用正则表达式又快又脏:
private String extractUrl(Path path) {
try {
String content = String.join("\n", Files.readAllLines(path));
Pattern pattern = Pattern.compile("\"url\".+\\s+\"(?<url>[^\\s\"]+)\"");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
return matcher.group("url");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
更好的解决方案是使用Jackson之类的JsonParser库:
private String extractUrl(Path path) {
try (BufferedReader reader = Files.newBufferedReader(path)) {
ObjectMapper mapper = new ObjectMapper();
MyObject object = mapper.readValue(reader, MyObject.class);
return object.getUrls().stream().findFirst().orElse(null);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
这使用文件内容的对象表示形式:
public class MyObject {
@JsonProperty("url")
private List<String> urls;
// getter and setter
}
但是最后,性能最高的解决方案可能是使用shell脚本。
答案 3 :(得分:0)
这是一个快速简单的awk脚本,它可以从基本目录执行所有工作。
名为script1.awk
的awk脚本
/https/{
if ($1 in urlArr) {
cmd = "rm " FILENAME;
print cmd;
//system(cmd);
} else {
urlArr[$1] = FILENAME;
}
}
首先使用以下命令运行脚本:
awk -f script1.awk dir{1,}/*.json
准备删除重复的json文件时,只需取消注释第5行(包含system(cmd)
的行)。并再次运行。
以下是一些解释:
awk
命令在子目录dir和dir1中的所有json文件上运行脚本script1.awk
。
脚本遍历每个文件,将具有https的URL文本提取到变量$ 1中。
如果关联数组urlArr中已经存在变量$ 1,则打印/删除文件。
否则将当前文件添加到关联数组urlArr中。
希望您喜欢这个简单的解决方案。