﻿# 介紹好用工具：功能完整且強大的 LFTP 命令列工具

我之前一直想找一套不錯的 FTP 傳檔工具，我說的不是 [FileZilla](https://filezilla-project.org/) 這種 GUI 工具，而是可以透過批次檔自動完成 FTP 檔案傳輸的 CLI 工具。最近終於讓我找到了一套非常理想的 [LFTP](http://lftp.yar.ru/) 工具，不但支援多種 FTP 通訊協定，其內建的命令與參數也超級多，功能強大好用，今天這篇文章我們就來介紹這套好用的 FTP 命令列工具！👍

![LFTP](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/bcdcb60f0eaaea61adc0-215955881-36350a60-a6d6-4bc8-b880-e5ce2dc08207.png)

### 安裝 LFTP 工具

-   Windows
    
    由於 [LFTP for Windows](https://nwgat.ninja/lftp-for-windows) 問題很多，建議不要在 Windows 安裝這套工具，你只要透過 WSL 執行 `lftp` 即可使用，也非常方便！
    
-   Ubuntu Linux
    
    ```bash
    sudo apt install lftp
    ```
    
-   Red Hat Enterprise Linux (RHEL) 8
    
    ```bash
    sudo dnf install lftp -y
    ```
    
-   CentOS or Red Hat Enterprise Linux (RHEL) 7
    
    ```bash
    sudo yum install lftp -y
    ```
    
-   macOS
    
    [MacPorts](https://ports.macports.org/port/lftp/)
    
    ```bash
    sudo port install lftp
    ```
    
    [Homebrew Formulae](https://formulae.brew.sh/formula/lftp)
    
    ```bash
    brew install lftp
    ```
    

### 體驗 lftp 的互動式 CUI 介面

-   進入 lftp 互動式 CUI 介面
    
    ```bash
    lftp
    ```
    
    ![lftp :~>](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/88f5073528bdb44f335a-215955600-c3326776-9e4c-41fe-9f7d-6e6130bb9418.png)
    
    若加上 `-d` 參數則代表進入 `debug` 偵錯模式，會顯示完整的 FTP 執行命令
    
    ```bash
    lftp -d
    ```
    
    > 上述命令都只是進入 lftp 的互動式 CUI 介面而已，還沒有對遠端 FTP Server 進行連線。
    
-   在 lftp 互動模式下輸入命令
    
    ```bash
    # 啟用等級 10 的偵錯技術並寫入 debug.log 檔案
    debug -o debug.log 10
    # 連接站台
    open myftp.servername
    # 輸入帳號密碼
    user username password
    # 進入資料夾
    cd /site/wwwroot
    # 列出當前目錄的檔案或子目錄清單
    ls
    # 設定傳檔時可以自動覆蓋同名檔案
    set xfer:clobber on
    # 自動下載所有當前目錄下的所有檔案
    mget *.html
    # 設定用 mirror 整批下載時要用幾條連線平行下載檔案
    set mirror:use-pget-n 5
    # 自動下載所有當前目錄與其子目錄下的所有檔案
    mirror .
    ```
    
    如果要批次上傳整個資料夾到 FTP 站台，可以在互動模式下輸入以下命令：
    
    ```bash
    mirror -R .
    ```
    
-   進入 lftp 互動式 CUI 介面並直接建立連線的方法
    
    可以直接輸入帳號密碼與主機名稱直接連線並登入，甚至可以直接進入遠端的 FTP 資料夾路徑
    
    ```bash
    lftp -u 'username,password' myftp.servername/remote/path
    ```
    
    由於預設 lftp 會優先採用比較安全的 `TLS` 加密連線，若你的 FTP Server 沒有支援 TLS 的話，可以用 `ftp://` 來表達主機位址
    
    ```bash
    lftp -u 'username,password' ftp://myftp.servername/remote/path
    ```
    
    帳號密碼部分也可以用標準 Bash Auth 的格式來連線
    
    ```bash
    lftp 'ftp://username:password@myftp.servername/remote/path'
    ```
    
-   使用 WSL 的注意事項 (Windows)
    
    在 Windows 透過 WSL 執行 lftp 時，在輸入帳號密碼的時候很有可能會出現問題，只要你的帳號或密碼有出現 `\` 或 `$` 等特殊字元，就可能會出現無法登入的狀況。
    
    我舉個例子來說，我們在 Azure Web App 下載的發行設定檔，當中的 FTP 帳號是這種格式：
    
    ```
    sitename\$sitename
    ```
    
    如果你用以下命令登入就會失敗：
    
    ```bash
    wsl lftp -u 'sitename\$sitename,password' waws-prod-hk1-001.ftp.azurewebsites.windows.net/site/wwwroot
    ```
    
    錯誤訊息會是：
    
    ```
    cd: Login failed: 530 User cannot log in.
    ```
    
    你可以用 `echo` 來測試看看實際傳入 WSL 執行的命令為何，你將會發現反斜線(`\`)不見了！
    
    ```bash
    PS> wsl echo lftp -u 'sitename\$sitename,password' waws-prod-hk1-001.ftp.azurewebsites.windows.net/site/wwwroot
    lftp -u sitename$sitename,password waws-prod-hk1-001.ftp.azurewebsites.windows.net/site/wwwroot
    ```
    
    所以正確的寫法變成以下這樣，就可以正常登入了！
    
    ```bash
    wsl lftp -u 'sitename\\\$sitename,password' waws-prod-hk1-001.ftp.azurewebsites.windows.net/site/wwwroot
    ```
    
    登入之後趕快加入書籤(Bookmark)，之後就不用再輸入帳號密碼了，讓我們繼續看下去！
    

### 使用 lftp 的書籤功能

lftp 內建書籤功能，他可以把目前 lftp 連接成功的**站台位置**、**帳號密碼**、**遠端資料夾路徑**，全部紀錄下來！👍

以下是建立書籤的步驟：

1.  先連入 FTP 站台、通過驗證並進入 `/site/wwwroot` 資料夾
    
    ```bash
    lftp -u 'username,password' myftp.servername/site/wwwroot
    ```
    
    > 帳號密碼部分用逗號分隔(`,`)
    
2.  從 lftp 的 CUI 介面透過 `bookmark` 命令建立書籤
    
    ```bash
    bookmark add mysite
    ```
    
    > 這些加入的書籤在 Ubuntu 的話預設會存放在 `~/.local/share/lftp/bookmarks` 檔案中，你也可以手動編輯該檔。
    

日後要使用書籤來進行連線，就很方便了，建議多加利用！👍

-   透過書籤連接 FTP 站台
    
    先連上 lftp 的 CUI 介面
    
    ```bash
    lftp -d
    ```
    
    使用 `bookmark list` 查詢所有書籤
    
    ```bash
    bookmark list
    ```
    
    透過 `open` 命令連接特定書籤
    
    ```bash
    open mysite
    ```
    
-   從 Shell 直接透過書籤連接 FTP 站台
    
    ```bash
    lftp mysite
    ```
    
-   從 Shell 取得 lftp 書籤清單
    
    ```bash
    lftp -c bookmark list
    ```
    
    > 這裡的 `-c` 是立即執行 **lftp command** 並**直接退出**的意思
    
-   從 Shell 編輯 lftp 書籤
    
    這個命令會開啟預設文字編輯器，讓你直接編輯書籤檔
    
    ```bash
    lftp -c bookmark edit
    ```
    

### 直接在 Shell 環境下操作 lftp

-   快速建立連線並執行指定命令
    
    這裡的 `-c` 是立即執行 lftp 的 command 並**直接退出**的意思。不過以下這個命令有點特別，我們在 `-c` 的**參數值**中用到了 `open` 命令，並透過 `-e` 帶入一個連線後要執行的命令(Expression)。這個命令 `open -e "ls" mysite` 所代表的意思是，先開啟 FTP 連線到 `mysite` 書籤，連線後立刻在 lftp 裡面執行 `ls` 命令：
    
    ```bash
    lftp -c 'open -e "ls" mysite'
    ```
    
    若有多組 lftp 命令要執行，可以用分號間隔(`;`)，他就會依序執行。例如：
    
    ```bash
    lftp -c 'open -e "echo List;ls;cd ..;echo List Parent Folder;ls" mysite'
    ```
    
-   批次下載遠端資料夾 (包含所有子資料夾)
    
    ```bash
    lftp -c 'open -e "mirror ." mysite'
    ```
    
    如果檔案數過多，可以考慮用多條連線平行下載，執行前設定 lftp 的 `mirror:use-pget-n` 選項即可：
    
    ```bash
    lftp -c 'open -e "set mirror:use-pget-n 5; mirror ." mysite'
    ```
    
-   批次上傳檔案到遠端 (包含所有子資料夾)
    
    ```bash
    lftp -c 'open -e "mirror -R ." mysite'
    ```
    
    如果檔案數過多，可以考慮用多條連線平行下載，執行前設定 lftp 的 `mirror:use-pget-n` 選項即可：
    
    ```bash
    lftp -c 'open -e "set mirror:use-pget-n 5; mirror -R ." mysite'
    ```
    

### 透過 lftp 進行批次操作

如果你的 FTP 操作很固定，但是步驟很複雜，那就可以改用 Script (腳本) 的方式執行，其設定步驟如下：

1.  先準備所有你要對 FTP 伺服器操作的命令清單，並儲存成 `*.lftp` 檔案
    
    建立一個檔名為 `getfiles.lftp`
    
    ```bash
    # 啟用等級 10 的偵錯技術並寫入 debug.log 檔案
    debug -o debug.log 10
    # 連接站台
    open myftp.servername
    # 輸入帳號密碼
    user username password
    # 進入資料夾
    cd /remote/path
    # 列出當前目錄的檔案或子目錄清單
    ls
    # 設定傳檔時可以自動覆蓋同名檔案
    set xfer:clobber on
    # 自動下載所有當前目錄下的所有檔案
    mget *.html
    # 會到上一層
    cd ../Diagnostics/
    # 列出遠端目錄的檔案清單
    ls
    # 在本地端建立資料夾
    !mkdir Diagnostics
    # 移動本地端預設目錄
    lcd Diagnostics
    # 取得 settings.json 檔案並儲存到 Diagnostics 資料夾下
    get settings.json
    # 移動本地端預設目錄到上一層
    lcd ..
    # 取得遠端檔案內容
    cat README.md
    ```
    
2.  執行批次命令
    
    ```bash
    lftp -f getfiles.lftp
    ```
    
    > 這裡加上 `-f` 的目的就是會讓批次命令執行完後自動退出。
    

### 總結

LFTP 還有好多功能，像是 Slots 功能也很帥，你可以在互動介面中切換多台不同的 FTP 伺服器連線，快速的切換與上傳下載檔案，真的非常酷。

我最喜歡 LFTP 的地方就是他很容易的可以幫我實現 FTP 的自動化作業，寫個 `*.lftp` 腳本丟進 `lftp` 來執行，再複雜的操作也不怕！👍

### 相關連結

-   [LFTP - sophisticated file transfer program](http://lftp.yar.ru/)
-   [GitHub - lavv17/lftp: sophisticated command line file transfer program (ftp, http, sftp, fish, torrent)](https://github.com/lavv17/lftp)
-   [LFTP - the manual page](https://lftp.yar.ru/lftp-man.html)
-   [lftp Tutorial (by Peter Matulis)](http://web.archive.org/web/20111024014512/http://tutorials.papamike.ca/pub/lftp.html)
