テクノロジー · 実用ガイド

FileZillaのMLSD一覧をCSVへ:ファイル名をそのまま保つ

名前のコンマ・セミコロン・有効な空白を残し、サイズの欠落とゼロを区別して、ディレクトリー項目もオフラインコピーに保ちます。

1件のMLSDを属性と未変更の名前に分けるオリジナルのイラスト
オリジナルのイラスト:最初の空白が区切りで、仮想名のセミコロンは名前の一部です。 Watch at Ease

FileZillaの生のディレクトリー一覧をコピー済みでも、すべてのセミコロンをコンマに置換する方法は適切なCSV変換ではありません。セミコロンはファイル名にも含まれ、名前のコンマや引用符には正しいCSV引用処理が必要です。

この手順は取得済みの1回分のMLSDデータをオフライン変換します。表示された名前・項目種別・元の属性を残しますが、ファイル取得、サーバー変更、再帰一覧作成、取得済み一覧の完全性証明はしません。

コピーがMLSDデータか先に確認する

既存の許可されたFTPまたはFTPS接続を使います。FileZillaの元のサポート議論では、デバッグ設定で生の一覧を表示する方法が説明されています。使用中の版にその項目がある場合だけ有効にし、対象フォルダーだけを更新します。ログでMLSDコマンドと正常完了を確認し、リモートフォルダーと取得時刻を別に記録します。現在のFileZilla画面は試していません。

その1回の正常な一覧からデータ項目だけをUTF-8プレーンテキストのmlsd.txtにコピーします。例は type=file;size=926; image.jpg です。名前の先頭・末尾の空白も含め、全文字を保ちます。変換器は生の項目、または正確な英語接頭辞Listing:とその後の1空白に対応します。時刻、翻訳された接頭辞、状態メッセージ、空の区切り行は含めません。

Unix/DOSのLISTテキスト、SFTP一覧、CLI JSONオブジェクト、未復号バイト、明らかな文字化けなら中止します。文字コードを推測したり元ログを上書きしたりしません。現代のFileZilla CLIには構造化JSON出力もあり、すでにCLIがある人には別の有効な経路ですが、この変換器には入力できません。

LinuxのBash端末でコピーを変換する

LinuxのBash端末でPython 3.9以降を使い、mlsd.txtのあるフォルダーに移動します。次の命令を直線引用符とバックスラッシュを保った1行でコピーし、新しい出力名を選びます。入力全件を検証してからmlsd.csvを排他的に作成し、入力は変更しません。

python3 -c "exec('import csv\\nimport sys\\n\\nrows = []\\nwith open(sys.argv[1], encoding=\"utf-8-sig\", newline=\"\") as source:\\n for number, raw in enumerate(source, 1):\\n line = raw.removesuffix(\"\\\\n\").removesuffix(\"\\\\r\")\\n if line.startswith(\"Listing: \"):\\n line = line[len(\"Listing: \"):]\\n facts, separator, name = line.partition(\" \")\\n if not separator or not name or (facts and not facts.endswith(\";\")):\\n raise ValueError(f\"Line {number}: expected one MLSD data entry\")\\n values = {}\\n for fact in facts[:-1].split(\";\") if facts else []:\\n key, equals, value = fact.partition(\"=\")\\n key = key.lower()\\n if not key or not equals or key in values or any(c.isspace() for c in fact):\\n raise ValueError(f\"Line {number}: malformed or duplicate fact\")\\n values[key] = value\\n size = values.get(\"size\", \"\")\\n if \"size\" in values and not (size.isascii() and size.isdecimal()):\\n raise ValueError(f\"Line {number}: invalid size\")\\n rows.append([name, values.get(\"type\", \"\"), size, values.get(\"modify\", \"\"), facts])\\nif not rows:\\n raise ValueError(\"No MLSD records: do not assume an empty directory\")\\nwith open(sys.argv[2], \"x\", encoding=\"utf-8-sig\", newline=\"\") as destination:\\n writer = csv.writer(destination)\\n writer.writerow([\"name\", \"type\", \"size_bytes\", \"modify_raw\", \"facts_raw\"])\\n writer.writerows(rows)\\nprint(len(rows), \"MLSD records exported; includes any directory entries\")\\n')" "mlsd.txt" "mlsd.csv"

5列はname、type、size_bytes、modify_raw、facts_rawです。最初の空白が属性と名前を区切り、その後の空白や名前のセミコロンはそのまま残します。属性名は大文字小文字を区別せず照合しますが、facts_rawには元の綴り・順序・値を保ちます。欠落したサイズは空欄で、返されたゼロは0です。

文字列として取り込み取得済みレコードを確認する

LibreOffice CalcでCSVを開き、UTF-8、コンマ区切り、半角の二重引用符を文字列区切りにします。区切りの結合、空白除去、数式評価をオフにし、5列をすべてテキストに指定します。取り込み画面が省略されるなら開く際にフィルター設定の編集を有効にします。=で始まる名前も数式ではなく文字列か確認します。

表示件数とヘッダーを除く解析後のCSVデータ行数を比べ、いくつかの正確な名前と属性を保存テキストに照合します。cdir、pdir、dirレコードは残してください。これらはディレクトリーで、レコード数はファイル数ではありません。typeの欠落は不明のままです。1つのパスに複数種別を返すサーバーもあるので、重複名も残し、自動で除去しません。

エラーとメタデータの限界を理解する

空入力、不正レコード、属性キーの重複、不正な指定サイズは出力作成前に停止します。既存の出力があるエラーには別の名前を選びます。ディスク・書き込み失敗では部分CSVが残る場合があり、その出力を使わず新しい名前で再実行して解析行数を比べます。本当に項目がない場合でも、この変換器は空一覧を証明しません。

サイズはサーバー報告の情報で、近似値の場合があります。欠落はゼロではなく、ディレクトリーサイズは再帰合計でもありません。modify_rawは未変換のサーバーテキストで、内容が同じ証拠ではありません。コピー時に抜けた文法的に正しい行は検出できません。正常な取得を自分で確かめ、元ログを残し、意図した情報だけを共有します。

この正確なBash命令で17件の人工データによる子プロセス検証を実行し、記号、Unicode、有効な空白、任意属性、ディレクトリー種別、不正入力、上書き拒否を確認しました。実際のFileZilla、FTPサーバー、Calc画面は実行せず、Windows・macOSも試していません。2点のイラストは仮想例で、画面写真ではありません。

欠落サイズ、ゼロ、保持されたディレクトリー種別を区別するオリジナルのイラスト
オリジナルのイラスト:欠落の空欄、返されたゼロ、ディレクトリー種別を区別します。 Watch at Ease