В надежде, что вопрос будет перенесен на соответствующий сайт, я все же отвечу здесь.
Вы можете добавить трубу с 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 мыслимых однобайтовых имен файлов, а также файл имя, начинающееся с пробела).