以下是我使用的命令示例:
rsync --list-only --include "*2012*.xml" -exclude "*.xml" serveripaddress::pt/dir/files/ --port=111 > output.txt
如何在没有权限,时间戳等额外信息的情况下获取文件名列表?
编辑:是否可以在新行上输出每个文件名?
答案 0 :(得分:7)
经过多年的努力,这是我解决这个古老问题的方法:
DIR=`mktemp -d /tmp/rsync.XXXXXX`
rsync -nr --out-format='%n' serveripaddress::pt/dir/files/ $DIR > output.txt
rmdir $DIR
答案 1 :(得分:2)
希望将问题转移到相应的网站,不过我会在这里回答。
您可以附加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
和许多其他工具的工作方式,以便即使包含换行符(有效!)的文件名也能正确保留:< / p>
rsync . | python rsf.py | xan -0 stat -c '%i'
正确显示每个给定文件的inode编号。
当然我可能错过了我没想到的那个或其他角落的情况,但我认为脚本正确处理了大多数情况(我测试了所有255个可想到的单字节文件名以及文件名称以空格开头。)
答案 2 :(得分:0)
rsync ... | sed -E 's|^([^\s]+\s+){4}||'
答案 3 :(得分:0)
进一步到https://stackoverflow.com/a/29522388/2858703
如果您的mktemp
支持--dry-run
选项,则无需实际创建临时目录:
rsync -nr --out-format='%n' serveripaddress::pt/dir/files/ $(mktemp -d --dry-run) > output.txt