这是我正在使用的命令的示例:
rsync --list-only --include "*2012*.xml" -exclude "*.xml" serveripaddress::pt/dir/files/ --port=111 > output.txt
如何获得仅列出文件名的列表,而没有诸如权限,时间戳等额外信息?
编辑:是否可以在新行上输出每个文件名?
希望问题将移至适当的站点,不过我会在这里回答。
您可以在管道上附加awk
:
rsync ... | awk '{ $1=$2=$3=$4=""; print substr($0,5); }' >output.txt
[这通过从第5个字段输出所有内容来消除所有不需要的信息,但是仅当输出格式的前四个字段都在某处没有附加空格时才起作用(这不太可能)。>>
如果文件名以空格开头,则此awk
解决方案将不起作用。
一种更强大的解决方法可能是一个相当复杂的程序,它也会做出假设。
以这种方式工作:对于每一行,
/
而不是-
分隔-它与ISO 8601不兼容。)情况变得更糟:对于非常神秘的极端情况,还有更多需要注意的事情:文件名可以转义。某些不可打印的字节由转义序列(#ooo
,其八进制代码为ooo
)替换,该过程必须相反。
因此,如果我们想正确执行,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')
这将输出以NUL字符分隔的文件名列表,类似于
find -print0
和许多其他工具的工作方式,因此即使包含换行符(有效!)的文件名也可以正确保留:
rsync . | python rsf.py | xan -0 stat -c '%i'
正确显示每个给定文件的索引节点号。
确实,我可能错过了我没有想到的一个或另一个特殊情况,但是我认为脚本可以正确处理大多数情况(我测试了所有255个可想到的一字节文件名以及一个文件名以空格开头)。
经过多年的努力,这是我对这个古老问题的解决方案:
rsync ... | sed -E 's|^([^\s]+\s+){4}||'