【问题标题】:How to shell script a list of files with their modification time on mingw?如何在mingw上编写带有修改时间的文件列表?
【发布时间】:2013-07-23 15:13:15
【问题描述】:

免责声明:这个问题的存在是因为Unity3D and its library issue

我尝试获取 current git-cache-meta.sh 并在 Windows 上使用它。它不起作用。

我得到的第一个错误是在这一行:

$ find `git ls-files`
find: invalid predicate `-'

将其更改为原始的 find $(git ls-files) 也不起作用(即两种语法都不好)。

invalid predicate 肯定是由于一个名为"boo - foo.bar" 的文件。所以我尝试运行find "$(git ls-files)"。然后变成了very ugly error/bug

我想知道为什么command substitution(奇怪的$()在mingw 上不起作用,但更重要的是:

我们怎样才能让git-cache-meta.shmingw正确工作?

正如您在下面看到的,我实际上设法在没有该关键字的情况下回答了这个问题 -> 正确。所以我仍然希望有人能想出一个快速而干净的解决方案

【问题讨论】:

    标签: git shell find mingw


    【解决方案1】:

    原始脚本以优雅而复杂的风格编写(可能比必要的还要多)。我重写了它,去掉了大部分复杂性。我不知道 mingw 上哪个功能中断了,但这更有可能起作用:

    GIT_CACHE_META_FILE=.git_cache_meta
    case $@ in
        --store)
            git ls-files|while read file; do
                find "$file" \( -printf 'chown %U %p\n' \) \
                   \( -printf 'chgrp %G %p\n' \) \
                   \( -printf 'chmod %#m %p\n' \) \
                   \( -printf 'touch -c -d -m "%TY-%Tm-%Td %TH:%TM:%TS" "%p"\n' \)
            done | tee $GIT_CACHE_META_FILE
            ;;
        --apply)
            sh -e $GIT_CACHE_META_FILE
            ;;
        *)
            echo "Usage: $0 --store|--apply"; exit 1
            ;;
    esac
    

    唯一可能出错的是系统上的一个可执行文件不支持此处使用的所有选项。那将是:find、chown、chgrp、touch 和 chmod。

    【讨论】:

    • 太棒了!!我仍然遇到一个奇怪的错误,导致它在整个过程中停止,但这正是我所要求的,而且解决这个问题比原来的要好得多!谢谢。
    • 当我使用它时,我会改变一些事情:(1)删除tee并直接使用redirection>,如果这样更快(或者添加> /dev/null,如果它不是)。 (2) 删除find 并使用其他任何东西。 findMinGW 的罪魁祸首,非常有缺陷的实现。正如我上面提到的,它在我的情况下崩溃,堆栈倾倒STATUS_ACCESS_VIOLATION。因此,例如,touch 的行可能是:echo "touch -c -d -m \"$(date -r "$file" +'%F %T')\" \"$file\"";(正如我在回答中所做的那样)。再次,非常感谢你,piojo!
    • 很高兴我帮了一点忙。我无法删除“查找”用法,因为我不知道如何获取该行中请求的所有元数据,而且我实际上不知道哪些元数据是必要的。
    • 请注意,如果您想将其用于 Unity 游戏数据并希望避免未定义的 Unity 状态,则应仅在文件内容与原来相同的情况下恢复旧元数据。如果文件内容自导入以来不同,Unity 需要查看更新的时间戳。这意味着,如果您需要使用非常旧的结帐(一切都已更改),那么漫长的重新导入时间将无济于事。
    • 我希望它这么简单......从我的测试来看,Unity 毕竟不只使用时间戳来重建库。
    【解决方案2】:

    我发现了一个大而复杂的,因此难以移植且缓慢的解决方案。太慢了。哇哇太慢了。花费一分钟多的时间来浏览我的 git,它有大约 9k 个文件。但是,这里有thanks to Dave Taylor、google 和许多手册页。基本上,使用 for 和 Dave 的 hack 而不是 find

    git ls-files -d > .temp_gitcachemeta
    for s in $(git ls-files | grep -vf .temp_gitcachemeta | sed 's/ /_+_/g');
        do t="$(echo $s | sed s'/_+_/ /g')";
        echo "touch -c -m -d \"$(date -r "$t" +'%F %T')\" \"$t\"";
    done
    rm .temp_gitcachemeta ;;
    

    在这里使用临时文件是因为 mingw 似乎也不支持process substitution

    【讨论】:

      【解决方案3】:

      MinGW 喜欢调用本地 Windows 工具,这些工具会在每行的末尾添加一个回车(CR,\r)。所以你可以用$(commandname | sed $'s/\r$//')或类似的东西替换$(commandname)

      另一种选择是尝试更多的 Unix-y,例如 Interix/SFU/SUA 或 Cygwin 或 MSYS 或 AT&T UWIN。

      至于一般的元数据,您的问题将是像 chownchgrpchmodtouch 这样的东西在 Windows® 平台上的行为会有所不同,有些东西甚至不存在,尤其是在FAT 文件系统,而 NTFS 具有一组完全不同的元数据(时间戳的不同格式、ACL 而不是 Unix 用户/组/其他权限等),因此可能需要了解 Unix 脚本世界的人进行一些开发工作 和 NT平台很好。

      最后,我想说这个脚本是一个安全漏洞,因为它只评估存储的命令,所以如果其他人有能力写入 .git_cache_meta 文件,他们将拥有你的系统。

      【讨论】:

      • (1) 关于 CR 的好主意!但使用| sed $'s/\r$//' 不起作用。 (2)我正在使用mingw,因为这是git附带的,所以我真的不想使用其他任何东西(因为我正在尝试制作一个git钩子)。 (3) touch 似乎工作正常。我并不真正关心其余的,但它们似乎也可以毫无问题地工作。 (4) 该死,我根本不会去想这种漏洞……无论如何,如果有人恶意访问该文件,他已经在其他地方找到了更糟糕的漏洞。 (最后)到目前为止,我无法使用这个答案。 :( 但是谢谢。
      • 另外,我刚刚尝试了理论(1)并做了git ls-files > textfile。不管我怎么做,文本文件永远不会带来任何 CR。它只是 LF(或“0a”,或 ASCII 10)。所以这可能不是问题。另外,错误确实指向 "-",所以我猜 MinGW 没有正确解释在命令替换下包含连字符的文件名,无论出于何种原因(错误)。
      • 好的。对不起,但显然这不是手头的问题。 (我已经看到了问题所在,这就是我建议它的原因。)祝你好运!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-04
      相关资源
      最近更新 更多