rsync, чтобы получить список только имен файлов - PullRequest
9 голосов
/ 01 февраля 2012

Вот пример команды, которую я использую:

rsync --list-only --include "*2012*.xml" -exclude "*.xml" serveripaddress::pt/dir/files/ --port=111 > output.txt

Как получить список только имен файлов без дополнительной информации, такой как разрешения, метка времени и т. Д .?

Редактировать: А можно ли вывести каждое имя файла на новой строке?

Ответы [ 3 ]

7 голосов
/ 08 апреля 2015

После многих лет работы вот мое решение этой извечной проблемы:

DIR=`mktemp -d /tmp/rsync.XXXXXX`
rsync -nr --out-format='%n' serveripaddress::pt/dir/files/ $DIR > output.txt
rmdir $DIR
2 голосов
/ 02 февраля 2012

В надежде, что вопрос будет перенесен на соответствующий сайт, я все же отвечу здесь.

Вы можете добавить трубу с awk:

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

Это устраняет всю нежелательную информацию, выводя все из 5-го поля, но работает только в том случае, если ни одно из первых четырех полей в выходном формате не получает где-то дополнительный пробел (что маловероятно).

Это решение awk не будет работать, если имена файлов начинаются с пробела.

Еще более надежным способом решения может быть довольно сложная программа, которая также делает предположения.

Работает так: для каждой строки

  • Отрезать первые 10 байтов. Убедитесь, что за ними следует ряд пробелов. Отрежь их тоже.
  • Отрежьте все следующие цифры. Убедитесь, что за ними следует один пробел. Отрежь это тоже.
  • Обрезать следующие 19 байтов. Убедитесь, что они содержат дату и отметку времени в соответствующем формате. (Я не знаю, почему компоненты даты разделяются / вместо - - это не соответствует ISO 8601 .)
  • Убедитесь, что теперь следует один пробел. Отрежь это тоже. Оставьте все следующие пробельные символы без изменений, так как они принадлежат имени файла.
  • Если тест прошел все эти проверки, вполне вероятно, что оставшаяся часть этой строки будет содержать имя файла.

Это становится еще хуже: для очень эзотерических угловых случаев есть еще больше вещей, которые нужно посмотреть: имена файлов можно экранировать. Некоторые непечатаемые байты заменяются escape-последовательностью (#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 мыслимых однобайтовых имен файлов, а также файл имя, начинающееся с пробела).

0 голосов
/ 25 октября 2013

rsync ... | sed -E 's|^([^\s]+\s+){4}||'

...