AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 554956
Accepted
macxpat
macxpat
Asked: 2019-12-01 08:35:41 +0800 CST2019-12-01 08:35:41 +0800 CST 2019-12-01 08:35:41 +0800 CST

使用 shell 工具 awk 编辑 fslint 的输出 | grep | sed

  • 772

任务是根据一组规则将此文本文件(实用程序的输出fslint)转换为 bash 脚本,其中包含rm要删除的重复文件的命令行和要保留的文件的注释行。

规则基本上是说:只删除特定目录中的重复文件。

目标是清理多年来在多个操作系统(Mac OS X、Windows、Linux)上积累的大约 1 TB 的重复数据。所有数据都已复制到 Linux 驱动器。

#3 x 697,612,024        (1,395,236,864) bytes wasted
/path/to/backup-100425/file_a.dat
/another/path/to/backup-disk-name/171023/file_a.dat
/yet/another/path/to/labs data/some/path/file_a.dat
#4 x 97,874,344 (293,634,048)   bytes wasted
/path/to/backup-100425/file b.mov
/another/path/to/backup-140102/file b.mov
/backup-120708/Library/some/path/file b.mov
/some/other/path/to/backup-current/file b.mov
#2 x 198,315,112        (198,316,032)   bytes wasted
/path/to/backup-100425/file_c.out
/another/path/to/backup-disk-name/171023/file_c.out

第一行表示有 3 个相同的副本,file_a.dat接下来的 3 行列出了它们的路径。理想情况下,应在此处删除 2 个副本。带有 6 位数字的目录(YYMMDD 格式的日期)就是我所说的历史备份目录。

将按此顺序应用于每组相同文件的规则是:

  1. 如果文件位于包含目录的路径中Library,请保留它。
  2. 如果文件在labs dataor中backup-current,请保留它,并删除历史备份目录中的所有重复项。
  3. 如果文件位于历史备份目录中,请将文件保留在最新的备份目录中,并删除较旧的副本。
  4. 否则保留文件。

这是所需的输出:

#!/bin/bash
#3 x 697,612,024        (1,395,236,864) bytes wasted
rm '/path/to/backup-100425/file_a.dat'
rm '/another/path/to/backup-disk-name/171023/file_a.dat'
#/yet/another/path/to/labs data/some/path/file_a.dat
#4 x 97,874,344 (293,634,048)   bytes wasted
rm '/path/to/backup-100425/file b.mov'
rm '/another/path/to/backup-140102/file b.mov'
#/backup-120708/Library/some/path/file b.mov
#/some/other/path/to/backup-current/file b.mov
#2 x 198,315,112        (198,316,032)   bytes wasted
rm '/path/to/backup-100425/file_c.out'
#/another/path/to/backup-disk-name/171023/file_c.out

我对 shell 工具 awk、grep 和 sed 不是很熟悉,在阅读了这个帖子后,我意识到我的初稿在概念上是错误的,“对 [I] 在命令式语言(如 C)中所做的事情的天真翻译”。

事实上,我们在这里处理的不是文件,而是一个文件的内容。

在这种情况下使用 shell 脚本是否合适?
如果是的话,一个高效的脚本会是什么样子?

编辑:在阅读了@Ed的答案和代码后,我试图澄清任务和要求,完美地解决了这个问题。

shell-script awk
  • 2 2 个回答
  • 96 Views

2 个回答

  • Voted
  1. Best Answer
    Ed Morton
    2019-12-01T13:11:23+08:002019-12-01T13:11:23+08:00

    考虑到我愿意投入多少时间来尝试,我不明白你的要求列表,但这里有一个脚本来分类和打印你似乎感兴趣的文件类型,希望你能弄清楚其余的:

    $ cat tst.awk
    /^#/ { prt(); print; next }
    { files[$0] }
    END { prt() }
    
    function prt(   file, isLibrary, isLabsBack, isNothing) {
        for (file in files) {
            if ( file ~ /(^|\/)Library(\/|$)/ ) {
                isLibrary[file]
            }
            else if ( file ~ /(^|\/)(labs data|backup-current)(\/|$)/ ) {
                isLabsBack[file]
            }
            else {
                isNothing[file]
            }
        }
        for (file in isLibrary) {
            print "Library", file
        }
        for (file in isLabsBack) {
            print "LabsBack", file
        }
        for (file in isNothing) {
            print "Nothing", file
        }
        delete files
    }
    

    .

    $ awk -f tst.awk file
    #3 x 697,612,024        (1,395,236,864) bytes wasted
    LabsBack /yet/another/path/to/labs data/some/path/file_a.dat
    Nothing /another/path/to/backup-disk-name/171023/file_a.dat
    Nothing /path/to/backup-100425/file_a.dat
    #4 x 97,874,344 (293,634,048)   bytes wasted
    Library /backup-120708/Library/some/path/file b.mov
    LabsBack /some/other/path/to/backup-current/file b.mov
    Nothing /path/to/backup-100425/file b.mov
    Nothing /another/path/to/backup-140102/file b.mov
    #2 x 198,315,112        (198,316,032)   bytes wasted
    Nothing /path/to/backup-100425/file_c.out
    Nothing /another/path/to/backup-disk-name/171023/file_c.out
    
    • 2
  2. macxpat
    2019-12-06T08:44:21+08:002019-12-06T08:44:21+08:00

    对于感兴趣的人,这是给出问题中提到的所需输出的代码。这只是对@Ed 真正智能代码的微小改编。

    BEGIN { print "#!/bin/bash" }
    /^#/ { prt(); print; next }
    { files[$0] }
    END { prt() }
    
    function prt(   file, isDate, isKeep, isDelete, backup, latest, pats) {
        # file exists in a current backup directory (yes|no)
        backup = "no"
        # latest historical backup date
        latest = "000000"
        for (file in files) {
            if ( file ~ /\/Library\// ) {
                # files to check manually
                isKeep[file]
            }
            else if ( file ~ /\/(labs data|backup-current)\// ) {
                # backup files to keep
                isKeep[file]
                backup = "yes"
            }
            else if ( match(file, /\/(backup-disk-name\/|backup-)([0-2][0-9][0-1][0-9][0-3][0-9])\//, pats) != 0 ) {
                # files in historical backup directories
                if ( pats[2] > latest ) {
                    latest = pats[2]
                }
                isDate[file] = pats[2]
            }
            else {
                # unclassified files to check manually
                isKeep[file]
            }
        }
        for (file in isDate) {
            if ( isDate[file] == latest && backup == "no") {
                isKeep[file]
            }
            else {
                isDelete[file]
            }
        }
        for (file in isKeep) {
            print "#", file
        }
        for (file in isDelete) {
            # use single quotes to escape special characters in file
            # use gensub() to escape single quotes in file
            print "rm", "'" gensub(/'/,"'\\\\''", "g", file) "'"
        }
        delete files
    }
    

    最后,我想分享一些想法。我希望我不会离题太多。
    几周前,我决定最终清理那些可怕的备份数据(有些文件有超过 10 个重复项)。但我找不到自动化任务的工具。而且我不想为此启动一个 C 程序,也不想采用 Perl 的方式。所以我知道我必须(而且我想)走壳路。但我不知道从哪里开始,卡在第一行。

    看了很多,还是很迷茫。所以我决定在 SE 上发布我的问题。
    当我第一次阅读@Ed 的代码时,我想“这到底是怎么回事!”。然后,当我拿到它时,我意识到这是一段出色的代码,高效且清晰。

    所以我们在这里。大约一周前,我awk对 RegExp 一无所知。现在,感谢@Ed 的贡献,我已经能够编写“我的”第一个awk脚本,更好地了解 RegExp 世界,并完成手头的任务。更重要的是,我现在有足够的信心自己深入研究 RegExpawk和其他文本处理 shell 工具。这也激励我为 SE 做出更多贡献。
    我只是想分享我的个人经历,给那些可能像我一样被困在一个问题上的人希望,比如面对一座山。

    • 0

相关问题

  • 打印文件行及其长度的脚本[关闭]

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 按分隔符拆分并连接字符串问题

  • 多行文件洗牌

  • MySQL Select with function IN () with bash array

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    模块 i915 可能缺少固件 /lib/firmware/i915/*

    • 3 个回答
  • Marko Smith

    无法获取 jessie backports 存储库

    • 4 个回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    user12345 无法获取 jessie backports 存储库 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl 为什么大多数 systemd 示例都包含 WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve