rsync获取仅文件名列表

use*_*282 10 filenames rsync file list

这是我正在使用的命令的示例:

rsync --list-only --include "*2012*.xml" -exclude "*.xml" serveripaddress::pt/dir/files/ --port=111 > output.txt
Run Code Online (Sandbox Code Playgroud)

如何在没有权限,时间戳等额外信息的情况下获取文件名列表?

编辑:是否可以在新行上输出每个文件名?

Wil*_*ken 8

经过多年的努力,这是我解决这个古老问题的方法:

DIR=`mktemp -d /tmp/rsync.XXXXXX`
rsync -nr --out-format='%n' serveripaddress::pt/dir/files/ $DIR > output.txt
rmdir $DIR
Run Code Online (Sandbox Code Playgroud)

  • 此外,这可能有效,但我不确定是否记录:`rsync -nr --out-format ='%n'serveripaddress :: pt/dir/files// dev/false> output.txt`和不,`/ dev/null`不会工作 (2认同)

glg*_*lgl 3

希望问题能转移到适当的网站,我还是会在这里回答。

您可以附加一个管道awk

rsync ... | awk '{ $1=$2=$3=$4=""; print substr($0,5); }' >output.txt
Run Code Online (Sandbox Code Playgroud)

这通过输出第五个字段中的所有内容来消除所有不需要的信息,但仅当输出格式中的前四个字段都没有在某处获得额外的空格时才有效(这不太可能)。

如果文件名以空格开头,则此awk解决方案将不起作用。

更可靠的解决方法可能是一个相当复杂的程序,它也做出假设。

它的工作方式如下:对于每一行,

  • 截掉前 10 个字节。验证它们后面是否有多个空格。把它们也剪掉。
  • 剪掉所有后面的数字。验证它们后面是否有一个空格。把它也剪掉。
  • 截掉接下来的 19 个字节。验证它们是否包含适当格式的日期和时间戳。(我不知道为什么日期的组成部分用/而不是分隔-- 它不符合ISO 8601。)
  • 验证现在后面是否有一个空格。把它也剪掉。保留所有后续空白字符不变,因为它们属于文件名。
  • 如果测试通过了所有这些验证,则该行的其余部分可能会包含文件名。

情况变得更糟:对于非常深奥的极端情况,还有更多需要注意的事情:文件名可以被转义。某些不可打印的字节被转义序列(#oooooo它们的八进制代码)替换,这个过程必须相反。

因此,如果我们想正确地做到这一点,那么awk无论是简单的脚本还是简单的脚本都无法做到这一点。sed

相反,可以使用以下 Python 脚本:

def rsync_list(fileobj):
    import re
    # Regex to identify a line
    line_re = re.compile(r'.{10} +\d+ ..../../.. ..:..:.. (.*)\n')
    # Regex for escaping
    quoted_re = re.compile(r'\\#(\d\d\d)')
    for line in fileobj:
        match = line_re.match(line)
        assert match, repr(line) # error if not found...
        quoted_fname = match.group(1) # the filename part ...
        # ... must be unquoted:
        fname = quoted_re.sub( # Substitute the matching part...
            lambda m: chr(int(m.group(1), 8)), # ... with the result of this function ...
            quoted_fname)                      # ... while looking at this string.
        yield fname

if __name__ == '__main__':
    import sys
    for fname in rsync_list(sys.stdin):
        #import os
        #print repr(fname), os.access(fname, os.F_OK)
        #print repr(fname)
        sys.stdout.write(fname + '\0')
Run Code Online (Sandbox Code Playgroud)

这会输出由 NUL 字符分隔的文件名列表,类似于find -print0许多其他工具的工作方式,因此即使包含换行符(有效!)的文件名也能正确保留:

rsync . | python rsf.py | xan -0 stat -c '%i'
Run Code Online (Sandbox Code Playgroud)

正确显示每个给定文件的索引节点号。

当然,我可能错过了我没有想到的一个或其他极端情况,但我认为该脚本正确处理了大多数情况(我测试了所有 255 个可想象的单字节文件名以及以空间)。

  • awk 可能更适合这个,因为 awk 理解最后一个字段运算符 `rsync ... | awk '{ 打印 $NF }'` (2认同)