Използвам rsync много. Използвам го за копиране на файлове на USB устройства, във виртуални машини или Docker контейнери, за споделяне на файлове между компютри у дома, за архивиране на неща на отдалечени машини или просто за копиране в локалната папка на Dropbox. И през повечето време изтеглям файлове от няколко отдалечени папки на моя компютър.

Извършвам всичките си файлови операции в терминала. Намирам това за по-бързо и по-удобно от щракване в GUI файловия мениджър от някакъв вид. Всъщност съм толкова непохватен с тези, че обикновено накрая премествам нещо важно някъде, където не му е мястото. Преди много, много години, когато бях млад младши разработчик на първата си работа, преместих важен проект в мрежов дял в папка с брат или сестра. Всичко, което исках да направя, е да сложа мишка от другата страна на клавиатурата и я хванах с лявата си ръка. О, това беше голямо бедствие: хората тичаха наоколо и търсеха папката с проекта, мислейки, че сме хакнати. Намерих го след 10 минути.

За да не повтарям тези сериозни грешки от миналото, просто се придържам към командния ред тези дни. Проблемът с командния ред обаче е, че не е много визуален. Особено когато става въпрос за отдалечени системи. Довършването на локални файлове в zsh е доста добро. И след като се сдвои с размит съпоставител като fzf, става удоволствие да се правят почти всякакви файлови операции в терминала.

В продължение на няколко години разчитах на zsh автоматично довършване на отдалечен път за rsync. Работи почти толкова добре, колкото и за локалните файлове. Просто въведете няколко символа, натиснете TAB и той автоматично довършва името на файла вместо вас. Ако името е двусмислено, ще се появи списък със съвпадения, където можете да изберете име с клавишите със стрелки. Доста стандартно изживяване с обвивка.

Все пак има проблем. Тъй като това е отдалечена система, отнема секунда или две за автоматично попълване. Това е досадно. Освен това се довършва автоматично само в текущата директория и ще трябва да натискам TAB много пъти, преди да получа пълния път. И мога да изтегля само един файл или папка наведнъж. Ето демо. Болезнено е да гледаш колко е бавен:

https://asciinema.org/a/EIc6s9XzvncvUAl7DYgVuWLvp?autoplay=1

Където има проблем, трябва да има решение. И както обикновено се случва с командния ред, решението е Bash скрипт:

#!/bin/bash
set -eo pipefail

HOST=${DL_HOST:-dev.somehost.to}
DIR=${DL_DIR:-files}

if [[ "$1" == "-h" || "$1" == "--help" ]]; then
    echo "USAGE: dl [dir [host]]"
    exit
fi

if [[ "$1" != "" ]]; then
    DIR="$1"

    if [[ "$2" != "" ]]; then
        HOST="$2"
    fi
fi

REMOTE="$HOST:$DIR/"

rsync -a "$REMOTE" \
    | ruby -ne 'puts $_.split(/\s+/, 5).last' \
    | fzf -m --height 50% \
    | rsync -avP --no-relative --files-from - "$REMOTE" .

Работи така:

https://asciinema.org/a/BwmSUZ7lK0mCk9Ot7797QNqQv?autoplay=1

Първо използва rsync, за да изброи всички файлове в отдалечената папка във формат, подобен на ls -l:

drwxr-xr-x          4,096 2019/03/01 23:23:25 src
-rw-r--r--            261 2019/02/20 23:11:49 src/PasswordManagerAccess.csproj
drwxr-xr-x          4,096 2019/03/01 23:23:25 src/Common
-rw-r--r--            379 2019/02/20 23:11:49 src/Common/BaseException.cs
-rw-r--r--            906 2019/03/01 23:23:25 src/Common/ClientException.cs
-rw-r--r--          3,454 2019/03/01 23:23:25 src/Common/Crypto.cs
-rw-r--r--            241 2019/02/20 23:11:49 src/Common/ExposeInternals.cs
-rw-r--r--          6,868 2019/03/01 23:23:25 src/Common/Extensions.cs
-rw-r--r--          1,178 2019/02/20 23:11:49 src/Common/HttpClient.cs
-rw-r--r--            487 2019/02/20 23:11:49 src/Common/IHttpClient.cs
-rw-r--r--          7,267 2019/02/20 23:11:49 src/Common/JsonHttpClient.cs
...

Това се предава във вграден Ruby скрипт, който извлича 5-та колона и всички интервали, които може да има. И резултатът от това влиза в fzf за интерактивен избор. След като приключи, това вече най-накрая се предава в друго копие на rsync, което получава списък с файлове на стандартния вход (--files-from -). Много готино. Допълнителното предимство: сега мога лесно да избирам няколко файла.

Скриптът взема името на отдалечената папка и хоста по избор от параметрите на командния ред или променливите на средата. Най-често използваният път, който реших да кодирам твърдо, за да върна моя RSI с няколко години.

Първоначално публикувано в detunized.net на 1 март 2019 г.